java.lang.NoClassDefFoundError

在JAVA开发中,main线程中抛出java.lang.NoClassDefFoundError是一个非常普遍且比较难解决的问题。解决这个问题的复杂性主要取决于你的软件大小和中间件部署情况,尤其要考虑在应用中出现的数量众多的classloader的情况。

本文将从一个比较高的角度看这个问题,主要是介绍java classloader机制。

那么,什么是java.lang.NoClassDefFoundError呢?

我们先简单的看一下这个问题,这个runtime异常是JVM抛出的,当JVM发现一个classloader试图去Load一个class,而此class在当前的classloader tree中找不到的时候,就会抛出此异常。

很明显,这个问题是运行期的问题,在编译期一切正常。

那么,解决起来很简单,就是把jar包放到classpath下不就行了么?

ok,到这里还不行,这个问题解决起来不是那么容易的,在运行期的程序classpath中加入缺少的jar包仅仅是一种解决方法。关键是,我们必须掌握此种异常的根本原因,以后解决此问题就可以以不变应万变。这就是我写这个文章的初衷。

现在,先记住,此问题不一定是由于在classpath中缺少class的定义。

java classloader概述

在深入分析之前,我们必须掌握java classloader的基本原理。class loader是一个java对象,它负责load所有的class,负责查找、加载、生成一个class的基本定义信息。classloader自身采用了委托代理机制来查询class,每一个classloader的实例都有一个父classloader,所以,当一个应用的classloader去加载class A的时候,首先发生的事情是classloader委托其父classloader去加载class A,经过一串链式查找后,最终任务会落在JVM的系统启动classloader上。

那哪里会出问题?当你期望你的应用classloader能加载class A,但是当class A被其任意一个父classloader查询到并加载,那么就可能会出现java.lang.NoClassDefFoundError。当所有的父classloader都找不到class A的时候,才会由应用自己的classloader尝试加载。


NoClassDefFoundError 问题原因1:缺少jar包

首先最常见的原因是classpath的配置问题。例子程序:

本例子程序尝试创建一个新的CallerClassA实例,然后执行他的一个方法,此方法引用了类ReferencingClassA,本例子演示了classpath问题导致的NoClassDefFoundError ,本例子还打印了当前的classloader chain的情况,以便进一步的分析。这个打印信息对你以后分析此类问题也很有帮助的:

程序
Java代码
public class NoClassDefFoundErrorSimulator {
public static void main(String[] args) {

System.out
.println("java.lang.NoClassDefFoundError Simulator");

// Print current Classloader context

System.out.println("\nCurrent ClassLoader chain: "
+ ClassloaderUtil.getCurrentClassloaderDetail());

// 1. Create a new instance of CallerClassA

CallerClassA caller = new CallerClassA();

// 2. Execute method of the caller

caller.doSomething();

System.out.println("done!");

}
}


Java代码
public class CallerClassA {
private final static String CLAZZ = CallerClassA.class.getName();

static {

System.out.println("Classloading of " + CLAZZ + " in progress..."
+ ClassloaderUtil.getCurrentClassloaderDetail());

}

public CallerClassA() {

System.out.println("Creating a new instance of "
+ CallerClassA.class.getName() + "...");

}

public void doSomething() {

// Create a new instance of ReferencingClassA

ReferencingClassA referencingClass = new ReferencingClassA();

}
}


Java代码
public class ReferencingClassA {

private final static String CLAZZ = ReferencingClassA.class.getName();

static {

System.out.println("Classloading of " + CLAZZ + " in progress..."
+ ClassloaderUtil.getCurrentClassloaderDetail());

}

public ReferencingClassA() {

System.out.println("Creating a new instance of "
+ ReferencingClassA.class.getName() + "...");

Maps.newHashMap();

}

public void doSomething() {

// nothing to do...

}
}


打印classloader工具类:

Java代码
public class ClassloaderUtil {
public static String getCurrentClassloaderDetail() {

StringBuffer classLoaderDetail = new StringBuffer();

Stack<ClassLoader> classLoaderStack = new Stack<ClassLoader>();

ClassLoader currentClassLoader = Thread.currentThread()
.getContextClassLoader();

classLoaderDetail
.append("\n-----------------------------------------------------------------\n");

// Build a Stack of the current ClassLoader chain

while (currentClassLoader != null) {

classLoaderStack.push(currentClassLoader);

currentClassLoader = currentClassLoader.getParent();

}

// Print ClassLoader parent chain

while (classLoaderStack.size() > 0) {

ClassLoader classLoader = classLoaderStack.pop();

// Print current

classLoaderDetail.append(classLoader);

if (classLoaderStack.size() > 0) {

classLoaderDetail.append("\n--- delegation ---\n");

} else {

classLoaderDetail.append(" **Current ClassLoader**");

}

}

classLoaderDetail
.append("\n-----------------------------------------------------------------\n");

return classLoaderDetail.toString();

}
}


正常运行:
Java代码
java -classpath .;../guava-12.0.jar NoClassDefFoundError.NoClassDefFoundErrorSimulator
java.lang.NoClassDefFoundError Simulator

Current ClassLoader chain:
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-----------------------------------------------------------------

Classloading of NoClassDefFoundError.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of NoClassDefFoundError.CallerClassA...
Classloading of NoClassDefFoundError.ReferencingClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of NoClassDefFoundError.ReferencingClassA...
done!


异常重现:
Java代码
java -classpath . NoClassDefFoundError.NoCl
java.lang.NoClassDefFoundError Simulator

Current ClassLoader chain:
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-----------------------------------------------------------------

Classloading of NoClassDefFoundError.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of NoClassDefFoundError.CallerClassA...
Classloading of NoClassDefFoundError.ReferencingClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-----------------------------------------------------------------

Creating a new instance of NoClassDefFoundError.ReferencingClassA...
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/Maps
at NoClassDefFoundError.ReferencingClassA.<init>(ReferencingClassA.java:28)
at NoClassDefFoundError.CallerClassA.doSomething(CallerClassA.java:31)
at NoClassDefFoundError.NoClassDefFoundErrorSimulator.main(NoClassDefFoundErrorSimulator.jav
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 3 more


发生了什么?当你在classpath中不包含guava的引用的时候,由于ReferencingClassA在运行期引用了此类,导致了classloader报告找不到此类,从而出现NoClassDefFoundError。

classloader分析

注意:
Java代码
Classloading of NoClassDefFoundError.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
-------------------------


sun.misc.Launcher$AppClassLoader是系统的classloader,负责根据classpath设置在启动的时候加载应用需要的class。

sun.misc.Launcher$ExtClassLoader是扩展classloader,负责从java_home/lib/etc以及其他使用java.ext.dirs配置的目录从加载扩展java class。

从打印结果可以看出,sun.misc.Launcher$ExtClassLoader是系统classloader的实际父类。

建议处理策略

分析异常堆栈,找到缺少的java类名称,在classpath中验证,确保编译和运行期都能找到此类。
基于大模型RAG的配电工作领域私有知识库项目(含python源码+详细说明文档+向量数据库+运行截图等) 项目介绍 旨在为基层配电工作人员提供一个集成了文档处理、知识管理和智能问答功能的工具。该项目通过挂载私有知识库的方式,弥补了大模型在行业细分领域知识准确性不足的问题,为一线电力工作人员提供了更加精准和稳定的知识支持。 主要功能】 支持多种文档格式上传,包括PDF、Word、Excel等 集成企业级文档解析器MinerU,对文档进行清洗和处理 基于LlamaIndex框架对文档进行向量化存储 支持关键词检索和语义检索相结合的混合检索方式 可接入在线大模型本地大模型进行智能问答 支持本地Qwen3系列模型推理模式的开启与关闭 提供Gradio网页界面和FAST API接口供用户交互 【技术栈】 Python LlamaIndex MinerU Gradio 【备注】 1、该资源内项目代码百分百可运行,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 【特别强调】 1、csdn上资源保证是完整最新,会不定期更新优化; 2、请用自己的账号在csdn官网下载,请勿第三方代下,否则博主不对您下载的资源作任何保证,且不提供任何形式的技术支持和答疑!!! 3、运行问题可私信博主,可远程部署
03-08
### 关于MinerU的技术信息 MinerU是一个一站式的开源高质量数据提取工具,支持PDF、网页以及多格式电子书等多种形式的数据源中的内容抽取工作[^2]。对于希望从不同类型的文件或者在线资源里高效获取有用资料的研究人员或是开发者来说非常实用。 #### 获取途径 - **官方网站**: 可访问[MinerU官网](https://mineru.net/)了解更多信息并下载软件。 - **GitHub仓库**: [MinerU GitHub页面](https://github.com/opendatalab/MinerU)提供了完整的项目代码和开发文档,方便有兴趣深入了解或参与到这个项目的个人查阅。 - **线上演示环境**: 如果想要先体验一下MinerU的功能而不必立即安装本地版本,则可以尝试进入[线上Demo入口](https://mineru.net/OpenSourceTools/Extractor)[^1]。 #### Docker启动指南 为了便于部署和服务运行,在Docker容器中启动MinerU服务的方法如下所示: ```bash docker run -itd --name=mineru_server --gpus=all -p 8888:8000 quincyqiang/mineru:0.2-models ``` 这条命令会创建一个新的名为`mineru_server`的Docker实例,并将其内部端口映射到主机上的指定端口(这里默认为8888),同时分配所有的GPU给此容器使用以便加速某些计算密集型任务。需要注意的是,这里的端口号可以根据实际情况灵活调整[^5]。 #### 功能特性概述 作为一款专注于提升用户体验的产品,MinerU不仅限于基本的文字识别与结构化转换能力;更重要的是其具备高度灵活性——由于采用了开放源码的形式发布,任何人均可根据特定应用场景的需求对其进行个性化修改和发展,从而更好地服务于不同的业务流程。此外,这种模式也鼓励了更多人的加入和技术交流活动的发生,共同推动着整个生态系统的进步与发展。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值