关于Jar加载顺序的问题分析

关于Jar加载顺序的问题分析,第1张

公司在做技术升级,升级日志后遇到应用部署A节点正常,B节点失败诡异情况,而后一段时间再次遇到同类问题,决定有必要一探究竟。

B节点失败的错误信息:

猜测:A节点正常,是因为先加载了sl4j-api.jar中的LocationAwareLogger.class,而B节点失败,是先加载了activemq-all.jar中的LocationAwareLogger.class,启动时程序找不到对应的方法报错。

应用运枯碧行在Tomcat容器,翻看类加载部分的源码。slf4j包Logger类加载器是Tomcat的ParallelWebappClassLoader,由父类WebappClassLoaderBase实现类加载功能。

类加载入口:

关注首次class文件从jar包中找到的过程。调用StandardRoot.getResourceInternal寻找class,顺序就是循环allResources(格式:List<List<WebResourceSet>>)。

集合classResources存了WEB-INF/lib目录的Jar资源,在Tomcat启动时调用processWebInfLib()方法初始化。

最终在DirResourceSet类list(String path)方法,其实调用的是java.io.File类list()方法,list调的是UnixFileSystem的native的没磨举list()方法。注释及解释;

翻开jdk8对应的OpenJDK源码,UnixFileSystem的list方法,调用的是目录 *** 作函数opendir.

继续向下查 *** 作系统,opendir返回值定义

通过 http://man7.org/linux 关于dirent的排序解释。

命令 ll -f 与opendir函数readdir顺序相同。

继续向下查是文件系统的实现,CentOS 6使用的是Ext4,文件顺序与目录文件的大小是否超过一个磁盘块和文件系统计算的Hash值有关。

因Java语言的跨平台特性,在class首次从jar中找到对应的文件游慎时,查找的顺序是文件 *** 作系统实现决定,与inode值无关。那么像active-all.jar将依赖一起打包的方式极易出现这类问题!!!

感谢前人栽树:

http://man7.org/linux/man-pages/man3/readdir.3.html

https://blog.csdn.net/peter_cloud/article/details/9240317

function dir_size($dir,$url){

$dh = @opendir($dir)//打开目录,返回一个目录流

$return = array()

$i = 0

while($file = @readdir($dh)){ //循环读取目录下蔽虚的文件

if($file!='.' and $file!='..'){

$path = $dir.'/'棚册.$file//设置目录,用宏和燃于含有子目录的情况

if(is_dir($path)){

}elseif(is_file($path)){

$filesize[] = round((filesize($path)/1024),2)//获取文件大小

$filename[] = $path//获取文件名称

$filetime[] = date("Y-m-d H:i:s",filemtime($path))//获取文件最近修改日期


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/8176942.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-14
下一篇 2023-04-14

发表评论

登录后才能评论

评论列表(0条)

保存