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的环境变量