前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ClassNotFoundException,NoClassDefFoundError,NoSuchMethodError排查

ClassNotFoundException,NoClassDefFoundError,NoSuchMethodError排查

作者头像
LNAmp
发布2018-09-05 15:28:43
1.9K0
发布2018-09-05 15:28:43
举报

前言

在使用java开发的过程中时常会碰到以上三个错误,其中NoClassDefFoundError、NoSuchMethodError两个error遭遇得会多一些。本文会简单分析三个异常发生的原因,并给出排查思路和相关工具。

定义

NoClassDefFoundError

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found. The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.

ClassNotFoundException

Thrown when an application tries to load in a class through its string name using: The forName method in class Class. The findSystemClass method in class ClassLoader . The loadClass method in class ClassLoader.

这两者都发生在运行期‘找不到需要的类’,但是需要注意的是ClassNotFoundException出现主要是由于在运行期尝试根据类名加载(通过Class.forName、ClassLoader.findSystemClass、ClassLoader.loadClass),但是找不到需要加载的类。ClassNotFoundException的异常场景有限,所以通常遭遇得比较少,如果遭遇了只要查找classpath是是否真的存在对应的类即可。平时遭遇的更常见的与‘找不到类’相关的错误是NoClassDefFoundError

NoClassDefFoundError

这个错误发生的场景就比较多了,较为常见的有:

  • 运行期真真找不到对应的类

例如A.jar的A.class依赖了B.jar的B.class,但是B.jar中由于某些原因并不存在B.class,此时就会抛出NoClassDefFoundError

  • 加载的类初始化错误

加载的class在初始化(loaded->linked->initialized)过程中出错了,初始化过程不可逆,以后凡是使用该class的地方都会抛出NoClassDefFoundError。这个错误通常是发生在clinit方法中,具体可能是静态变量,静态代码块。可参考寒泉子大大写的不可逆的类初始化过程 。通常错误堆栈表现为:

代码语言:javascript
复制
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class xxxx

...

如果你运气好的话,可能在该错误的上方看到java.lang.ExceptionInInitializerError的错误堆栈从而找到对应出错的地方;如果运气不好的话,该异常可能被吞掉,如果出问题的类你有权限修改的话,你可以显式catch异常打印日志,如果是二方包或者三方包的话...可能要使用比较tricky的手段了。

NoSuchMethodError

这个比较好理解了,在运行时找不到对应的类的对应方法,通常由于jar包依赖冲突导致。

排查思路与工具

ClassNotFoundException

由于是出现在运行期,我们要确定是否真的不存在该类,推荐使用脚本扫描war包(重点找lib包),此扫描脚本 来自于阿里的哲良大大。

代码语言:javascript
复制
sh /home/admin/devops/find-in-jars.sh -d . 'xxx.class'

如果没有找到,则加入对应的相关jar包即可

NoClassDefFoundError

首先看对应的错误堆栈,如果错误堆栈类似于:

代码语言:javascript
复制
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class xxxx

...

则表明是类的初始化过程发生了不可逆错误,参考上文所说的解决方案。

如果堆栈类似于:

代码语言:javascript
复制
java.lang.NoClassDefFoundError: com/taobao/pamirs/base/log/ErrorMonitorLog

没有出现‘ Could not initialize class’等关键字,此时可参考ClassNotFoundException的排查方法,使用扫描脚本确定war包是否真的存在该类,不存在的话则添加相关的jar包。

NoSuchMethodError

这个错误多半是由于jar包依赖冲突导致,依赖冲突是一个非常DT的问题。NoSuchMethodError出现是多半是存在两个同fully qualified name的class,刚好优先加载到了少了方法的那个。更为DT的是可能在不同机器上表现不一致(首先加载哪个class顺序不确定),‘对于classloader而言,找文件的过程取决于文件系统返回的顺序,简单的说,在linux上取决于两个inode的顺序’。

上面有些扯远了...解决这个问题先找到错误堆栈:

代码语言:javascript
复制
NoSuchMethodError: com.foo.SomeService.doSmth()Z

通过扫描脚本扫描lib包,看是否存在两个同fully qualified name的class出现在两个不同的jar版,如果存在,则排除其中一个版本的jar包。

但是需要注意的是,也有一种可能性是扫描com.foo.SomeService 会发现只存在一个对应class name的class文件。这时候需要调整下思路了,很可能是其父类类加载冲突了。比如说曾经遭遇过org.apache.log4j.DailyRollingFileAppender.setAppend NoSuchMethodError,排查半天后发现是其父类org.apache.log4j.FileAppender类加载冲突了。

Maven依赖树

由于集团多使用maven,由于依赖冲突会导致如上所述的NoSuchMethodError错误,在遭遇此类问题时通常会需要打印出应用的maven依赖树,通过我们会使用以下几种方式:

  • maven命令
代码语言:javascript
复制
mvn dependency:tree -Dverbose > tree.txt

当然加不加verbose也行

使用‘Dependency Analyzer’面板

  • 不知道为啥我的IDEA从某个版本开始就没法使用maven helper了,参考了其部分代码,自己写了个简易插件来生成maven的依赖树。使用方法是,在对应的pom文件右键选择maven菜单中的tree子菜单即可生成tree.txt文件,这个操作等同于在pom文件所在的子module里mvn dependency:tree -Dverbose > tree.txt。此插件源码在此,里面也附上了可安装的jar,下载安装即可使用。

总结

本文简述了ClassNotFoundException,NoClassDefFoundError,NoSuchMethodError的发生场景,给出了相关的排查思路与排查工具。

参考文献

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.04.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 定义
  • NoClassDefFoundError
  • NoSuchMethodError
  • 排查思路与工具
    • ClassNotFoundException
      • NoClassDefFoundError
        • NoSuchMethodError
          • Maven依赖树
          • 总结
          • 参考文献
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档