如何排查jar包冲突_怎么检查网络冲突

如何排查jar包冲突_怎么检查网络冲突在测试脚本编写和应用部署时,经常遇到的一个问题是:java.lang.NoSuchMethodError。这个问题产生的根本原因是运行时应用加载的jar包版本不是应用代码真正需要的版本。要解决这个问题,就要让应用加载真正“HasSuchMethod”的类所在的jar包。解决这个问题,我把它归纳为以下几步:验证加载内容、查找包含该类的jar包、查找应用适用的jar版本、查看出错应用加载的jar包位置

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

    在测试脚本编写和应用部署时,经常遇到的一
个问题是
: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是clas
sdump工具,它通过Serviceability Agent技术在运行时dump指定的类的字节码文件。2是jdgui,这是使用得最多的反编译工具,它可以把clas
sdump工具dump出来的字节码文件反编译成java代码,可以更直观得查看应用中加载的类是什么样子。
    clas
sdump工具的使用:
    命令: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的类就好。
如何排查jar包冲突_怎么检查网络冲突

写好了这个类之后,编译,把这个类的class文件放到要执行ClassDump命令的目录下,执行时增加如下参数:-Dsun.jvm.hotspot.tools.jcore.filter=MyFilter,ClassDump就会在当前目录dump出com.taobao.eagleeye.EagleEye类的字节码。
    然后使用jd-gui,jd-gui是一个绿色工具,直接打开字节码文件,可以看到rpcClientRecv方法,这里就可以看到,实际上当前jvm加载的是一个没有参数的rpcClientRecv方法。
如何排查jar包冲突_怎么检查网络冲突

    查找包含该类的jar包、查找应用适用的jar版本
    确认了当前出现错误的应用中确实加载了不符合要求的类之后,就需要去看一下,这个类是从哪里来的,在哪个jar包中。做这件事情比较简单,只需要去eclipse中执行ctrl+shift+t,输入类名,就可以看到当前eclipse的工程中依赖的各个版本的包含这个类的jar包。接下来你可以把各个版本的类都打开,检查这些版本的jar包中是否有符合要求的方法,即方法签名符合rpcClientRecv(Ljava/lang/String;I)V的方法。方法签名识别:其中L开头,;结尾的字符串标识了一个对象类型,这里的第一个参数是java.lang.String类型,第二个参数是int类型,V表示void类型返回。详细的jvm中字段类型和方法签名表示见下图:
如何排查jar包冲突_怎么检查网络冲突
如何排查jar包冲突_怎么检查网络冲突

    通过这个步骤,我们知道了实际上我们的应用需要什么版本的jar包,那么,接下来自然就会想要知道应用当前加载的是什么版本的jar包,又是在哪里加载进来的。

    
查看出错应用加载的jar包和jar包位置
    在这个步骤,要想知道应用加载的是jar包的什么版本,需要使用jvm类加载跟踪器这个工具,这是一个基于java agent、instrument的,用于排查jar包冲突、类冲突、类版本冲突、NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError 等类加载相关问题的辅助工具。这个工具的能够定时得把新加载入虚拟机类个jar包等数据输出到指定的html文件中。
    工具的使用方式是:首先,下载得到
jvminspect.jar;其次,修改目标应用的jvm配置,在jvm参数上增加如下的配置:
JAVA_OPTIONS=$JAVA_OPTIONS -javaagent:jvminspect.jar=outputfile=jvm.inspect.output,flushIntervalSecond=300 -DHtmlFlusher.enableHyperlink=false;其中
jvminspect.jar是下载得到的工具jar包,
jvm.inspect.output是输出的文件地址,
flushIntervalSecond参数指定的是定时刷新的时间间隔。增加了这个参数之后重启,就可以在
jvm.inspect.output文件中查看这个jvm进程加载类的情况了。
    我们关心的是出现NoSuchMethodError 所在的类,在这个例子中,这是com.taobao.eagleeye.EagleEye类,在输出的文件中我们可以看到这个类被jvm从jar包的哪个版本中加载,jar包的物理位置等信息。
如何排查jar包冲突_怎么检查网络冲突

    知道了这些信息,我们就很清楚得能够确定问题的原因。
    
替换错误jar包版本到需要的版本
    知道应用在那里加载了不期望被加载的jar包,我们就可以着手让应用把需要加载的正确版本包加载进来。不同的场景可以做不一样的操作,比如应用的war包中本身加载了错误版本的jar包,那你需要做的是修改应用的pom文件进行重新打包,把正确的jar包依赖到war包中;如果是由于某些环境的原因,classpath中存在了两个不同版本的jar包,那你就可以根据前面几步得到的信息,把错误版本(导致应用报NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError等错)的版本删除,留下应用代码实际上依赖的jar包。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170750.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ActionContext_session和page view

    ActionContext_session和page view在Struts2.0中,Action已经与Servlet API完全分离,这使得Struts2.0的Action具有了更加灵活和低耦合的特性,与Struts1.0相比较而言是个巨大的进步。虽然Struts2.0的Action已经与Servlet API完全分离,但我们在实现业务逻辑处理时经常需要访问Servlet中的对象,如Session、Application等。Struts2.0 提供了一个名

    2022年9月9日
    0
  • LSD算法

    LSD算法供参考https://blog.csdn.net/chishuideyu/article/details/78081643https://blog.csdn.net/tianwaifeimao/article/details/17678669

    2022年5月22日
    44
  • Android官方文档翻译-Broadcasts

    Android官方文档翻译-Broadcasts原文链接:https://developer.android.com/guide/components/broadcasts.html广播Android应用可以向Android系统和其他Android应用发送或从它们那接收广播消息,这类似于发布-订阅设计模式。当需要关注的事件发生时这些广播就会发送出去。例如Android系统在许多系统事件发生时会发送广播,比如当系统启动或设备开始充电时。应用也可以发

    2022年6月26日
    28
  • 关于kafka集群搭建前后

    关于kafka集群搭建前后近期搭建了kafka集群服务器,遇到了问题进行记录1.遇到某台服务器网卡出现问题,导致无效,因为网卡是集成的,即是zookeeper组中一个,也是kafka的brokers之一解决办法:重新更换服务器,重装系统,进行安全配置,在配置好zookeeper和kafka,和损坏的服务器一样的配置2.替换服务器后,遇到过了数据量太大,其中替换的服务器磁盘利用率不断增加,达到最大值,导致服务启动

    2022年4月29日
    31
  • oracle模糊查询方法_oracle模糊查询下划线

    oracle模糊查询方法_oracle模糊查询下划线在这个信息量剧增的时代,如何帮助用户从海量数据中检索到想要的数据,模糊查询是必不可少的。那么在Oracle中模糊查询是如何实现的呢? 一、我们可以在where子句中使用like关键字来达到Oracle模糊查询的效果;在Where子句中,可以对datetime、char、varchar字段类型的列用Like关键字配合通配符来实现模糊查询,以下是可使用的通配符:(1)%:零或者多个字符,

    2022年4月19日
    218
  • 视频编解码基本流程

    视频编解码基本流程视频编解码基本框架

    2022年7月13日
    13

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号