commons-io版本变动在windows环境下引发的NTFS ADS separator问题

起因

因业务需求,项目中引入了一个对方的业务jar包,但是发现代码却启动不起来了,报错:

org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'locations' threw exception; nested exception is java.lang.IllegalArgumentException: NTFS ADS separator (':') in file name is forbidden.

尽管本地环境(windows)启动不起来,但是打包后放入Linux容器中是正常运行的。

随即进入debug分析,定位异常位置,发现是在使用disconf的jar中会调用到commons-ioFilenameUtilsgetExtension方法,来获取一个文件的后缀,具体调用如下:

String extension = FilenameUtils.getExtension(fileName);

比如fileName为log4j2.xml,方法返回的就是xml

由于业务方引入的jar包中包含的commons-io的2.8.0的新包,IDEA启动时默认会使用该包,实际上原项目commons-io使用的是2.5版本。

分析

disconf使用的是org.apache.commons.io下的FilenameUtils,我们先看下2.5版本的实现:

public static String getExtension(final String filename) {  if (filename == null) {  return null;  }  final int index = indexOfExtension(filename);  if (index == NOT_FOUND) {  return "";  } else {  return filename.substring(index + 1);  }  
}

关注下indexOfExtension的实现:

public static int indexOfExtension(final String filename) {  if (filename == null) {  return NOT_FOUND;  }  final int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);  final int lastSeparator = indexOfLastSeparator(filename);  return lastSeparator > extensionPos ? NOT_FOUND : extensionPos;  
}

而2.8.0的commons-io的实现如下:

public static String getExtension(final String fileName) throws IllegalArgumentException {  if (fileName == null) {  return null;  }  final int index = indexOfExtension(fileName);  if (index == NOT_FOUND) {  return EMPTY_STRING;  }  return fileName.substring(index + 1);  
}
public static int indexOfExtension(final String fileName) throws IllegalArgumentException {  if (fileName == null) {  return NOT_FOUND;  }  if (isSystemWindows()) {  // Special handling for NTFS ADS: Don't accept colon in the fileName.  final int offset = fileName.indexOf(':', getAdsCriticalOffset(fileName));  if (offset != -1) {  throw new IllegalArgumentException("NTFS ADS separator (':') in file name is forbidden.");  }  }  final int extensionPos = fileName.lastIndexOf(EXTENSION_SEPARATOR);  final int lastSeparator = indexOfLastSeparator(fileName);  return lastSeparator > extensionPos ? NOT_FOUND : extensionPos;  
}

问题就出在这里,方法多了一个IllegalArgumentException异常,并且是特定在windows环境下才抛出NTFS ADS separator (':') in file name is forbidden.,这也就解释了为什么服务打包后在Linux环境下没有问题。

该方法的注释上也写了为什么会做这个改变:

Note: This method used to have a hidden problem for names like “foo.exe:bar.txt”. In this case, the name wouldn’t be the name of a file, but the identifier of an alternate data stream (bar.txt) on the file foo.exe. The method used to return “.txt” here, which would be misleading. Commons IO 2.7, and later versions, are throwing an {@link IllegalArgumentException} for names like this.

翻译过来就是,在windows上类似foo.exe:bar.txt的文件,bar.txt不是文件的名称,而是文件foo.exe上的备用数据流bar.txt的标识符。

NTFS中的备用数据流(Alternate Data Stream,ADS)允许将一些元数据嵌入文件或是目录,而不需要修改其原始功能或内容。

这个改动刚好是commons-io的2.7版本,命中了项目因为引入业务jar包导致的2.5->2.8.0的升级迭代。

解决

后续决定还是在业务jar中移除commons-io的2.8.0版本,沿用之前项目中的2.5版本。

总结

项目使用disconf来监听配置文件的变更,实际上传入的是类似classpath:log4j2.xml这样的fileName,导致的问题。

项目初步启动时,直接报错的堆栈中并没有关于commons-io的堆栈信息,只知道是disconf的bean无法启动,可以先从这个bean入手,逐步定位到是com.baidu.disconf.client.addons.properties.ReloadablePropertiesFactoryBean成员变量locations的问题,进而从setLocations这个方法定位到使用了FilenameUtils中的getExtension,从而得知是哪里的异常。

进而直接使用Dependency Analyzer,看到业务jar包引入了更新版本的commons-io,并通过对比两个版本的FilenameUtilsgetExtension方法的区别,了解本次异常的原因。

这是一次较为常见的组件变动引起的启动异常,但是实际上问题的表征并不能直接定位原因,合理利用debug,在项目启动时,添加断点,逐步分析,是开发者需要掌握的技能。

这个问题直接搜索是不太能得到答案的,但是分析问题的过程,是初学者逐步向熟练者进阶的必备技能,特此记录,以作参考。

参考

  1. NTFS ADS(备用数据流)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/79444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序与保持健康的六个秘诀

虽然编程并不被视为是一个高危职业,但我们发现一大批数量惊人的开发人员正遭受健康问题的折磨。坐在办公桌很舒适,但有研究表明,它并不像你想象的那样健康。幸运的是,有很多非常容易做到的方法可以改善你的健康。 1.锻炼 尽管这可能是最明显的方法,但很多开发人员常常会…

变压器寿命预测(python代码,Logistic Regression模型预测效果一般,可以做对比实验)

1.数据来源官网:Data for: Root cause analysis improved with machine learning for failure analysis in power transformers - Mendeley Data 点Download All 10kb即可下载数据 2.下载下来后是这样 每一列的介绍: Hydrogen 氢气; Oxyge…

Virtualbox中Ubuntu根目录空间不足

现象 Virtualbox中Ubuntu根目录空间不足 解决 动态存储 虚拟机关闭先在虚拟介质管理里把硬盘Size调大开启Ubuntu用Disks或者GParted重新调整分区大小重新启动 步骤参考: https://zhuanlan.zhihu.com/p/319431032 https://blog.csdn.net/ningmengzhihe/article/details/1272…

VirtualBox宿主机和虚拟机文件互传设置

一、如图1、2、3步骤,设置共享粘贴板和拖放为双向 二、 在启动的虚拟机设置的里面,安装增强插件,然后重启虚拟机。 三、在网络位置就可以看到了

Business Objects单一报表升级为全套商业智能BI产品,探索更多平台与行业

从Crystal Reports到Business Objects 1994年的时候,Crystal Decisions还只有单一的报表产品Crystal Reports,也是全球第一个Microsoft Windows环境下的报表制作工具。 与微软的合作过程中,Crystal Decisions不断进行产品更迭,于…

CentOS 7 调优之周期性的访问中断

文章目录 背景问题描述原因分析解决方案相关版本 背景 操作系统版本:CentOS Linux release 7.6.1810 (Core) 操作系统镜像安装后,未进行任何调整。正常部署应用,应用在 CentOS 7.9 未出现过此类现象。 问题描述 问题描述:负载教…

Pytorch 多卡并行(2)—— 使用 torchrun 进行容错处理

前文 Pytorch 多卡并行(1)—— 原理简介和 DDP 并行实践 介绍了使用 Pytorch 的 DDP 库进行单机多卡训练的方法,本文进一步说明如何用 torchrun 改写前文代码,以提高模型训练的效率和容错性torchrun 是从 Pytorch 1.9.0 开始引入的…

[管理与领导-93]:IT基层管理者 - 扩展技能 - 5 - 职场丛林法则 -7- 复杂问题分析能力与复杂问题的解决能力:系统化思维

目录 前言: 一、系统化思维 VS 分解思维 1.1 系统化思维 1.2 分解思维 二、中医与西医思维模式的区别 三、正向闭环/正反馈 VS 负向闭环/负反馈 VS 开环 3.1 开环与管理 3.2 闭环与管理 3.3 生态系统是闭环系统 3.4 团队是一个闭环系统 3.5 正向闭环/正反…

华为云云服务器云耀L实例评测 | 在华为云耀L实例上搭建电商店铺管理系统:一次场景体验

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

最优化:建模、算法与理论(典型优化问题

第四章 典型优化问题 4.1 线性规划 4.1.1 基本形式和应用背景 再次说明一下,其实这本书很多的内容之前肯定大家都学过,但是我觉得这本书和我们之前学的东西的出发角度不一样,他更偏向数学,也多一个角度让我们去理解 线性规划问…

STM32-HAL库06-硬件IIC驱动FM24CL16B非易失存储器

STM32-HAL库06-IIC驱动FM24CL16B非易失存储器 一、所用材料: STM32VGT6自制控制板 STM32CUBEMX(HAL库软件) MDK5 二、所学内容: 通过HAL库的硬件IIC对FM24CL16B存储器进行写与读取操作。 三、CUBEMX配置: 第一步…

【Cocos Creator 3.5实现赛车游戏】10.实现汽车节点的运动逻辑

转载知识星球 | 深度连接铁杆粉丝,运营高品质社群,知识变现的工具 项目地址:赛车小游戏-基于Cocos Creator 3.5版本实现: 课程的源码,基于Cocos Creator 3.5版本实现 上一节的学习后,您已经完成了对汽车节点的控制逻…

简单记一下Vue router 路由中使用 vue-i18n 进行标题国际化

引入状态管理和国际化文件 import store from ../store import i18n from /configs/i18n使用状态管理设置路由当前国际化选项 // 使用状态管理 i18n.locale store.state.setStore.i18n??zh路由中使用i18n { path: /login, name: login, component: LoginPage, meta: { ti…

四川玖璨电子商务有限公司:短视频运营理解

短视频运营是一种通过策划、执行和管理短视频内容以达到品牌目标的一项工作。在如今面临信息爆炸的时代,短视频已经成为了吸引用户注意力的一种重要方式。作为一种新兴媒体形式,短视频拥有跨时空、生动有趣、内容丰富的特点,因此得到了越来越…

信道分类 | 信道

文章目录 高斯信道带限信道 高斯信道 定义:功率限制为P的高斯信道容量为 C m a x f ( x ) : E X 2 P I ( X ; Y ) Cmax_{f(x):EX^2P}I(X;Y) Cmaxf(x):EX2P​I(X;Y) I ( X ; Y ) ≤ 1 2 l o g ( 2 π e ( P N ) ) − 1 2 l o g ( 2 π e N ) I(X;Y)\le \frac{1}{…

华为云云耀云服务器L实例评测|云耀云服务器购买流程与功能介绍

目录 概述什么是云耀云服务器L实例功能概述 技术参数处理器和内存存储和网络GPU加速 强大的计算能力高性能计算集群大规模并行计算 灵活可扩展的存储本地SSD存储产品购买流程 概述 什么是云耀云服务器L实例 云耀云服务器L实例是新一代开箱即用、面向中小企业和开发者打造的全新…

CocosCreator3.8研究笔记(十)CocosCreator 图像资源的理解

一、图像资源导入 Cocos Creator 可使用图像文件格式,支持 JPG、PNG、BMP、TGA、HDR、WEBBP、PSD、TIFF 等。 将图像资源直接拖拽到 资源管理器 即可将其导入 二、图像资源的类型 在 属性检查器 面板中便可根据需要设置图像资源的使用类型:raw 、 textu…

flask bootstrap页面json格式化

html <!DOCTYPE html> <html lang"en"> <head><!-- 新 Bootstrap5 核心 CSS 文件 --> <link rel"stylesheet" href"static/bootstrap-5.0.0-beta1-dist/css/bootstrap.min.css"><!-- 最新的 Bootstrap5 核心 …

纯小白安卓刷机1

文章目录 常见的英文意思刷机是什么&#xff1f;为什么要刷机&#xff1f;什么是BL锁&#xff08;BootLoader锁&#xff09;&#xff1f;我的机能够刷机吗&#xff1f;什么是Boot镜像/分区&#xff1f;什么是Recovery镜像/分区&#xff08;缩写为rec&#xff09;&#xff1f;什…

数据分析与可视化 Numpy数组

1.创建数组 import numpy as np anp.array([1,2,3,4]) aarray([1, 2, 3, 4]) print(a)[1 2 3 4] b np.array((2,4,6,8)) print(b)[2 4 6 8] cnp.array([[1,2,3,4],[5,6,7,8]]) print(c)[[1 2 3 4] [5 6 7 8]] dnp.array([1,2,3,4],dtypefloat64) print(d)[1. 2. 3. 4.] …