NoClassDefFoundError排坑经历

1. 前言

实习做NLP任务时,在离线train获得模型bin文件后,在部署到线上之前经常需要测试一下QPS等指标,用Java写了测试流程,用Maven打成jar包之后,上传到开发机。打包是用的clean package命令,但是传到服务器上却报main NoClassDefFoundError错误,遇到过两次,故作记录

2. 错误原因

NoClassDefFoundError是因为Java虚拟机在编译时能找到合适的类,而在运行时不能找到合适的类导致的错误。

3. 与ClassNotFoundException的区别

两者区别还蛮大的。
NoClassDefFoundError发生在JVM在动态运行时,根据提供的类名,在classpath中需要找到对应的类进行加载,当找不到这个类时,就会发生NoClassDefFoundError错误。
ClassNotFoundException完全是由于环境的问题导致的,在编译时就会报错,相对较容易解决。

4. 问题描述

我在项目引用了外部jar包,由于jar本身不支持maven,所以在使用和打包时,将jar文件添加在lib路径里,并在pom.xml文件里显式的配置了绝对引用路径,如下:

<dependency>
    <groupId>com.github.XXX</groupId>groupId>
    <artifactId>XXX</artifactId>artifactId>
    <version>0.1</version>version>
    <scope>system</scope>scope>
    <systemPath>/home/your/jar/path</systemPath>systemPath>
</dependency>dependency>

借助clean package命令进行打包,将jar包传到服务器,运行如下命令:java -cp XXX-1.0-SNAPSHOT-jar-with-dependencies.jar:. com.XXX.FasttextClassifier,终端提示找不到引用的外部类。

5. 解决方法

将引用的外部jar包在开发机上编辑生成jar包文件,更改运行命令为:java -cp XXX-1.0-SNAPSHOT-jar-with-dependencies.jar:my/path/to/XXX.jar:. com.XXX.FasttextClassifier,可以运行。
感觉是打包的问题,貌似并没有把依赖的包打包进来,在开发机上运行,还需要将引用的jar包路径用-cp命令复制到classpath路径里。

6.常见的排查原因

  • 对应的class在java的classpath中不可用
  • 你可能用jar命令运行你的程序,但类并没有在jar文件的manifestclasspath属性中定义
  • 可能程序的启动脚本覆盖了原来的classpath的环境变量
  • 因为NoClassDefFoundErrorjava.lang.LinkageError的一个子类,所以可能由于程序依赖的原生的类库不可用而导致的
  • 检查日志文件中是否有java.lang.ExceptionInInitializerError这样的错误,NoClassDefFoundError有可能是由于静态初始化失败导致的
  • 如果你工作在J2EE的环境,有多个不同的类加载器,也可能导致NoClassDefFoundError
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容