searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

java.lang.NoSuchMethodError一次诡异的启动失败查障及分析

2023-08-02 02:21:52
12
0

 

一、问题表现

   最近对JAVA程序进行了例行的迭代升级,但部署时出现了一个诡异的情况:同一个JAVA程序,部署在当前环境中多台机器节点时。只有一台IP为25的机器在JAVA程序启动时抛出了“java.lang.NoSuchMethodError”的异常,无法启动,但其它机器均表现正常。

    

二、问题分析

首先核查了环境中所有主机的LINUX版本、JDK版本、JAVA程序版本,发现全部一致,没有差异。那么问题来了:

“java.lang.NoSuchMethodError”这个异常,是因为什么问题引起?为什么只有25机节点失败。JAVA不是一次编译,处处运行吗?

 

JAR包冲突

其实有经验的JAVA开发人员,如果发现同一个JAR包在不同的环境中表现不一,而失败的节点抛出的异常是“java.lang.NoSuchMethodError”、

“java.lang.ClssNotFoundException”(非笔误,完整关键字无法提交),“java.lang.NoClassDefFoundError,java.lang.LinkageError”时,应该会马上联想到,九成是jar包冲突。不同的JAR包依赖有相同的类名,因为加载顺序未如预期。譬如本应加载A.JAR的MYCLASS,但结果加载到B.JAR的MYCLASS,最后的结果就是NoSuchMethodError,该依赖版本中的类中不存在该方法。

 

 

JAR包的加载顺序

当你的应用程序在CLASSPATH中需要加载大量的JAR包时,JAR包的加载顺序是和指定的顺序相关的。譬如 java -cp a.jar:b.jar,那么a.jar就会先于b.jar加载。那么当前程序是如何指定CLASSPATH的加载JAR包的呢?结果如下:

从上面的脚本可以看到,是以指定目录下的JAR文件来加载的?那马上就会迎来第二个问题

为什么25机的加载JAR包的顺序和其它机器不一样?查看CLASSPATH所在磁盘的文件系统:

25机:

其它机器:

 

只有25机的默认数据目录/data是EXT4文件系统,而其它机器均是XFS文件系统。

文件系统的文件加载顺序,依赖于底层文件系统返回的顺序,当不同环境之间的文件系统不一致时,就会出现有的环境没问题,有的环境出现冲突的情况。Ext4文件顺序与目录文件的大小是否超过一个磁盘块和文件系统计算的Hash值有关。

 

 

三、问题的解决方案

  • 临时方案,当前从日志中可以得知是NETTY类方法报错,优先加载NETTY的相关JAR包,问题解决。
  • 最终方案,在CLASSPATH中指定JAR的加载顺序。
0条评论
0 / 1000
c****n
5文章数
0粉丝数
c****n
5 文章 | 0 粉丝
原创

java.lang.NoSuchMethodError一次诡异的启动失败查障及分析

2023-08-02 02:21:52
12
0

 

一、问题表现

   最近对JAVA程序进行了例行的迭代升级,但部署时出现了一个诡异的情况:同一个JAVA程序,部署在当前环境中多台机器节点时。只有一台IP为25的机器在JAVA程序启动时抛出了“java.lang.NoSuchMethodError”的异常,无法启动,但其它机器均表现正常。

    

二、问题分析

首先核查了环境中所有主机的LINUX版本、JDK版本、JAVA程序版本,发现全部一致,没有差异。那么问题来了:

“java.lang.NoSuchMethodError”这个异常,是因为什么问题引起?为什么只有25机节点失败。JAVA不是一次编译,处处运行吗?

 

JAR包冲突

其实有经验的JAVA开发人员,如果发现同一个JAR包在不同的环境中表现不一,而失败的节点抛出的异常是“java.lang.NoSuchMethodError”、

“java.lang.ClssNotFoundException”(非笔误,完整关键字无法提交),“java.lang.NoClassDefFoundError,java.lang.LinkageError”时,应该会马上联想到,九成是jar包冲突。不同的JAR包依赖有相同的类名,因为加载顺序未如预期。譬如本应加载A.JAR的MYCLASS,但结果加载到B.JAR的MYCLASS,最后的结果就是NoSuchMethodError,该依赖版本中的类中不存在该方法。

 

 

JAR包的加载顺序

当你的应用程序在CLASSPATH中需要加载大量的JAR包时,JAR包的加载顺序是和指定的顺序相关的。譬如 java -cp a.jar:b.jar,那么a.jar就会先于b.jar加载。那么当前程序是如何指定CLASSPATH的加载JAR包的呢?结果如下:

从上面的脚本可以看到,是以指定目录下的JAR文件来加载的?那马上就会迎来第二个问题

为什么25机的加载JAR包的顺序和其它机器不一样?查看CLASSPATH所在磁盘的文件系统:

25机:

其它机器:

 

只有25机的默认数据目录/data是EXT4文件系统,而其它机器均是XFS文件系统。

文件系统的文件加载顺序,依赖于底层文件系统返回的顺序,当不同环境之间的文件系统不一致时,就会出现有的环境没问题,有的环境出现冲突的情况。Ext4文件顺序与目录文件的大小是否超过一个磁盘块和文件系统计算的Hash值有关。

 

 

三、问题的解决方案

  • 临时方案,当前从日志中可以得知是NETTY类方法报错,优先加载NETTY的相关JAR包,问题解决。
  • 最终方案,在CLASSPATH中指定JAR的加载顺序。
文章来自个人专栏
cygwing专栏
5 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0