- 浏览: 796824 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
huan19900606:
像haskell这些脚本语言很容易定义DSL,实现对应的词法语 ...
DSL的基本介绍(groovy来进行构建) -
express_wind:
https://yq.aliyun.com/album/130 ...
qlexpress规则引擎初探 -
readxuxuegang:
博主你好。如果groovy的代码是保存在数据库里,不是文件,这 ...
在java中使用groovy怎么搞 (java and groovy) -
express_wind:
hi,兄弟,有没有兴趣来阿里巴巴专门做这方面的研究,https ...
qlexpress规则引擎初探 -
langcaiye:
有2个问题请教:1. 这里的base32算法为什么需要以负数的 ...
【原】geohash算法详解
java类加载中的版本冲突是一个头疼的问题,这里列举几种排查问题以及处理的常用办法
有时候在测试环境下正常的,线上部分机器也是正常,但是有一些机器就会异常,这是啥原因?
因为jar包的加载顺序在不同的机器上面是不同的,一台机器多次重启,基本的顺序不会变,但是新的jar包就会有问题
在不同的机器上,对jar包中类的加载顺序有时候不是完全一致的,例如,在/home/admin/.default/lib 目录下的有个A.jar和b.jar,里面都有个叫SayHello的class,但A的SayHello里的功能(例如他打印的是“去你的”)和b的SayHello功能(例如他打印的是“你好”)不一样,
由于不同机器加载顺序可能不一致,那么就有可能A机器上先加载了A.jar的SayHello类(会打印出“去你的”),而B机器上加载了b.jar的SayHello类(会打印出“你好”)。
这个问题在特定的机器上,其加载顺序基本不变的,因此,一旦测试的时候没问题,那他就很难再重现出此问题,只有部署到线上多台机器上时,问题才可能会暴露出来。
(1)通过maven自带的几个工具来进行分析
1、mvn dependency:list能够列举出项目中的依赖情况
2、mvn dependency:tree打印出依赖出(\-代表行尾) 这个在排除依赖的时候非常有用,通过树状结构来查看jar包的加载情况
3、mvn dependency:analyzer 这个能够分析项目中的依赖情况。
Used undeclared dependencies 是指那些在项目中直接使用到的,但没有在POM中配置的依赖。要注意一点,这个分析是编译主代码和测试代码需要的依赖,运行时需要的没有打印出来。例如该例中可能项目中的一些类有关于spring-context的Java import声明,但spring-context这个依赖实际是通过传递性依赖进入classpath的,这就意味者潜在的风险。一般来说我们对直接依赖的版本变化会比较清楚,因为那是我们自己直接配置的,但对于传递性依赖的版本变化,就会比较模糊,当这种变化造成构建失败的时候,就很难找到原因。因此我们应当增加这些 Used undeclared dependencies 。
依赖分析还提供了 Unused declared dependencies 供我们参考,这表示那些我们配置了,但并未直接使用的依赖。需要注意的时,对于这些依赖,我们不该直接简单地删除。由于dependency:analyze只分析编译主代码和测试代码使用的依赖,一些执行测试和运行时的依赖它发现不了,因此还需要人工分析。通常情况,Unused declared dependencies 还是能帮助我们发现一些无用的依赖配置。
补充一个maven传递依赖的两个原则
(1)最短路径优先
例如项目A中有这样的依赖关系,A->B->C->X(1.0) A->D->X(2.0) 分别传递依赖了X包的两个版本,
此时X(1.0)的路径为3,X(2.0)的路径为2,maven优先使用2.0)这个包
(2)第一声明者优先
上面这个原则不能解决所有问题,例如X(1.0)和X(2.0)的路径相同,这时候会使用那个包?
在依赖路径长度相同的情况下,POM依赖声明的顺序决定了谁会被解析使用,顺序靠前的那个依赖优先使用。
例如:
A->B->Y(1.0) A->C->Y(2.0)
如果B的依赖声明在C之前,则Y(1.0)版本会被解析使用。
(2)在应用启动的时候通过-verbose来进行分析
这个能够辅助进行一些分析,不过jvm启动参数上面加入-verbose可能会导致jboss挂起,可以使用,但是不要作为常态化来使用
1、在JVM的启动参数里面加入“-verbose”,这样会在日志里面显示类加载的信息;
2、输出JVM启动的时候的信息到特定的文件(可选)-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=<path>
通过脚本抓取日志里面从WEB-INF中加载的jar包
grep '^\[Loaded.*/WEB-INF/lib.*' jboss_stdout.log | awk '{print $4 }' | cut -d'/' -f10 | cut -d']' -f1 |sort -u
(3)在编译阶段就预警出问题来,
在编译后,可以通过两种方式来进行
1、在WEB-INF目录下的lib中,解压jar包,然后递归比较类文件名称,如果有一个类名称相同的文件出现在两个jar包中,则有可能会发生冲突,提示出来即可
2、遍历maven插件,在编译的时候进行校验。
大体过程可以分为两步,第一步通过maven自带的API获取所有的jar包文件
第二步,遍历文件,将所有的类信息放到map或者set中,然后进行比较,如果文件曾经出现过,则提示有可能冲突。
private MavenProject project; private boolean failOnWarning; @SuppressWarnings("unchecked") public void execute() throws MojoExecutionException, MojoFailureException { Set<Artifact> artifacts = project.getArtifacts(); HashMap<String, Artifact> classAndArtifactMap = new HashMap<String, Artifact>(); boolean hasWarnings = false; for (Artifact artifact : artifacts) { ZipInputStream zis = null; try { zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(artifact.getFile()))); ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { if (entry.isDirectory() || !entry.getName().endsWith(".class")) { continue; } if (classAndArtifactMap.containsKey(entry.getName())) { hasWarnings = true; getLog().warn("DUPLICATED CLASS FOUND! " + entry.getName() + "\r\n\t" + artifact + "\r\n\t" + classAndArtifactMap.get(entry.getName())); break; } classAndArtifactMap.put(entry.getName(), artifact); } } catch (Exception e) { throw new MojoExecutionException("Unknown errors...", e); } finally { IOUtils.closeQuietly(zis); } } if (failOnWarning && hasWarnings) { throw new MojoFailureException("PLEASE CHECK ABOVE WARNINGS!!! There is duplicated classes found in your dependencies."); } }
第一种方式在排查问题的时候非常有用,第二种方式不推荐,极力推荐在编译阶段就把有可能存在类冲突的类查出来
发表评论
-
系统分布式情况下最终一致性方案梳理
2015-09-05 19:34 40806前言 目前的应用系 ... -
Storm核心概念剖析
2015-03-20 20:42 3177最近团队中有分析的场 ... -
池和流的两种数据处理方式
2014-11-19 22:59 1319在抽象层面,想了一下,目前很多的数据处理形式,一般分为池和流 ... -
关于CodeReview(java)
2014-10-29 20:42 1831关于codereview,在平时的开发中,经常忽略的环节,参 ... -
java中各种各样的数据结构
2014-07-13 20:26 2398在java中,有非常丰富的数据结构,可能是因为大多数的软件 ... -
关于JVM的ClassLoader(笔记)
2014-07-13 12:19 1794众所周知,java是编译型的语言,写的是java文 ... -
关于事务的几个概念介绍
2014-06-06 22:22 1890啥是事务? 有一组操 ... -
开发中遇到的编码问题
2014-05-22 19:39 17891、说到编码,最大的问题就是乱码了,为啥会有乱码呢 ? 因 ... -
ThreadLocal源代码解析
2014-04-24 17:54 2357最开始的时候,理解的ThreadLocal,我的理解是这样的 ... -
关于单例模式(代码篇)
2014-04-23 10:47 2366很早的时候,转发过一篇单例模式的文章:http://iamz ... -
今天遇到的两个spring相关的两个问题
2014-04-18 21:56 2493今天在项目中写代码,遇到两个Spring的问题,记录一下。再 ... -
Activiti中的命令模式解析
2014-04-11 13:10 3080最近在看Activiti的源代码,发现是基于命令模式进行的开 ... -
关于java中的本地缓存-总结概述
2014-03-31 19:00 18288java中的本地缓存,工作后陆续用到,一直想写,一直无从下 ... -
使用guava中的EventBus构建内存级别的事件引擎
2014-03-25 19:27 6315这个EventBus是guava中比较给力的一个类,从字面 ... -
DSL的基本介绍(groovy来进行构建)
2014-03-04 23:32 16926什么是DSL? 领域特定 ... -
qlexpress规则引擎初探
2014-02-25 22:28 24850qlexpress是啥? 这个是阿里内部的一个开源的jav ... -
在java中使用groovy怎么搞 (java and groovy)
2014-01-15 23:17 10841什么是groovy? 一种基于Java虚拟机的动态语言, ... -
java中记录方法调用时间,结果按照方法的层级树状的输出
2013-12-21 17:36 4621 在java中,最常用的埋点时间的方法就 ... -
一次CMS GC问题排查过程(理解原理+读懂GC日志)
2013-12-14 22:21 41219这个是之前处理过的一个线上问题,处理过程断断续续,经历了两 ... -
令牌桶算法和漏桶算法以及流量控制浅谈
2013-11-27 23:20 20703 在双十一等大促环节,系统需要限流,外部 ...
相关推荐
java类加载原理分析,引导类加载器,扩展类加载器,系统类加载器(也叫应用类加载器)
类加载分析工具,在应用部署后,可找出是哪个类呗加载了,在那个目录或者jar中,内部资料
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...
看完一个Java加载原理教程后,写了这个自己的类加载器,作个笔记,以便以且使用
JVM实战-JVM类加载机制案例分析
大幅提升工作效率~SecureCRT 8.0安装 & 加载配色方案.rar
什么是虚拟机类加载机制以及加载过程,以及类加载时机
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...
自定义类加载器实现自定义加载。自定义类加载器实现自定义加载
Java虚拟机类加载顺序,Java虚拟机类加载顺序,Java虚拟机类加载顺序
该文件是JVM中关于类加载机制的知识整理的思维导图,包括类加载机制概述、类加载的生命周期、加载时机、加载过程、类加载、类的初始化和实例化等几个大方面进行了讲解,其中类加载中还对JVM三种预定义类加载器进行了...
深入研究Java类加载机制 深入研究Java类加载机制 深入研究Java类加载机制 深入研究Java类加载机制
Java类加载器可以直接从Maven存储库加载并运行类,能在运行时解决依赖关系
【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!
java类加载器学习三、类加载器的委托模式
Java的类加载机制:加载,连接,初始化。JAVA类加载器: Bootstrap ClassLoader : 根类加载器, Extension ClassLoader: 扩展类加载器, System ClassLoader : 系统类加载器, Java反射
02 类加载子系统 PPT 介绍 JVM 的类加载子系统, 包括类加载阶段和流程、加载器分类和类加载机制等。
weblogic类加载过程简述weblogic类加载过程简述weblogic类加载过程简述weblogic类加载过程简述weblogic类加载过程简述weblogic类加载过程简述
Tomcat7.0.62 启动类加载日志
ClassLoader 三种类加载方式 Boostrap Extenxsion 以及Application ClassLoad分别适用的场景