jar包冲突 - wtdig/study GitHub Wiki
jar包冲突一
jar包冲突二
第一种参数:-javaagent:D:/jarconflict/jvminspect.jar=outputfile=D:/jarconflict/jvm.inspect.output,flushIntervalSecond=300 -
DHtmlFlusher.enableHyperlink=false
第二种参数:-verbose:class
window -- preferences -- java -- installed jres,选中jdk,选择edit,在Default vm arguments上添加以上参数(选择其中一种即可),在输出的文件
中查找指定类的所加载的jar包版本,在项目工程中,通过ctr+shift+t指令搜索指定类。
D:/jarconflict/jvminspect.jar 该jar包存储的位置;outputfile=D:/jarconflict/jvm.inspect.output,文件输出的路径,
jvm.inspect.output输出的文件名
在测试脚本编写和应用部署时,经常遇到的一个问题是:java.lang.NoSuchMethodError。这个问题产生的根本原因是运行时应用加载的jar包版本不是
应用代码真正需要的版本。要解决这个问题,就要让应用加载真正“HasSuchMethod"的类所在的jar包。解决这个问题,我把它归纳为以下几步:验证加
载内容、查找包含该类的jar包、查找应用适用的jar版本、查看出错应用加载的jar包位置、替换错误jar包版本到需要的版本。
验证加载内容
通常,发生了NoSuchMethodError,在报错中我们可以查看到应用真实需要的方法和方法签名,例如如下的报错:
java.lang.NoSuchMethodError: com.taobao.eagleeye.EagleEye.rpcClientRecv(Ljava/lang/String;I)V
表明应用需要的是EagleEye类中的包含方法签名如:void rpcClientRecv(String str,int i)的方法。知道了这一点,我就自然需要去看一下应
用中实际加载的EagleEye是什么样的情况,rpcClientRecv方法的签名是什么样子的。
要得到这些内容,可以用两个工具来获取,1是classdump工具,它通过Serviceability Agent技术在运行时dump指定的类的字节码文件。2是
jdgui,这是使用得最多的反编译工具,它可以把classdump工具dump出来的字节码文件反编译成java代码,可以更直观得查看应用中加载的类是什么样子。
classdump工具的使用:
命令:java -classpath ".:/opt/taobao/java/lib/sa-jdi.jar" sun.jvm.hotspot.tools.jcore.ClassDump 16528
其中-classpath把sa-jdi的jar包加入到classpath中,ClassDump 是执行字节码文件dump的main方法入口类,16528是目标进程的pid,可以用jps命令得到。
这样,ClassDump会把当前加载的所有Java类都dump到当前目录下,如果有全限定名相同但内容不同的类同时存在于一个Java进程中,那么dump的
时候会有覆盖现象,实际dump出来的是同名的类的最后一个。
如果需要指定被dump的类的范围,可以自己写一个过滤器,在启动ClassDump工具时指定
-Dsun.jvm.hotspot.tools.jcore.filter=filterClassName,如果需要指定dump出来的Class文件的存放路径,可以用
-Dsun.jvm.hotspot.tools.jcore.outputDir=path来指定,path替换为实际路径。
对于上面讲的例子,我们只需要EagleEye类的内容,那么,就可以写一个FilterClass类来进行dump的过滤,写这个过滤类,需要实现
sun.jvm.hotspot.tools.jcore.ClassFilter,具体实现如下图所示,InstanceKlass对应于HotSpot中表示Java类的内部对象,我们只要过滤类名
以com/taobao/eagleeye的类就好。