我向您建议的一系列文章将为您提供有关如何解决和解决此类问题的逐步方法。 我还将分享我在过去10年中观察到的最常见的Java NoClassDefFoundError问题模式。 还将提供示例Java程序,以简化您的学习过程。 我也鼓励您发表评论,分享您的问题案例,并就此问题向我提出任何问题。
该系列的第1部分将重点概述此Java运行时错误以及Java ClassLoader概述。
java.lang.NoClassDefFoundError –这是什么?
现在让我们开始对此问题进行简单的概述。 当ClassLoader尝试加载类的定义( 在您的应用程序代码等中引用的类)并且在当前ClassLoader树中找不到此类定义时,JVM会抛出此运行时错误。
基本上,这意味着此类Class定义是在编译时找到的,而在runtime时找不到的。
很简单,如何将缺少的类添加到类路径中呢?
嗯,不是那么快,这种类型的问题并不是那么容易解决。 将缺少的Class / JAR添加到运行时应用程序classpath / ClassLoader只是许多可能的解决方案之一。 关键是首先执行适当的根本原因分析。 这就是为什么我要创建整个系列。
现在,只需记住,这个错误并不一定意味着你缺少从你的“期望”类路径或ClassLoder这个类定义,所以请不要认为在这一点上任何东西。
Java ClassLoader概述
在继续进行之前,对Java ClassLoader原理有很高的了解是非常重要的。 经常调试NoClassDefFoundError问题的人很挣扎,因为他们缺乏对Java ClassLoader原理的正确了解和理解。 阻止他们查明根本原因。
类加载器是负责加载类的Java对象。 基本上,类加载器会尝试查找或生成构成该类定义的数据。 要理解的关键点之一是,默认情况下,Java类加载器使用委托模型来搜索类。 每个ClassLoader实例都有一个关联的父类加载器。 因此,假设您的应用程序类加载器需要加载类A。它将尝试做的第一件事是,在尝试查找类A本身之前,将对类A的搜索委托给其父类加载器。 您最终可以得到一个大型类加载器链,其中包含许多父类加载器,直至JVM系统类路径引导类加载器。
问题是什么? 好吧,如果从某个特定的父类加载器中找到了A类,那么如果希望应用程序(子类)加载A类,则该父类将为NoClassDefFoundError打开大门。 例如,第三方JAR文件依赖项只能存在于您的应用程序子类加载器中。
现在,让我们在Java EE企业环境的上下文中可视化整个过程,以便您更好地理解。

如您所见,子类加载器(Web应用程序)加载的任何代码都将首先委托给父类加载器(Java EE App)。 然后,此类父类加载器将委派给JVM系统类路径类加载器。 如果未从任何父类加载器中找到此类,则子类加载器将加载该类(假设已找到该类)。
请注意,Java EE容器(例如Oracle Weblogic)具有重写此默认类加载器委托行为的机制。 我将在以后的文章中再次讨论。
请随时发表您对到目前为止所学知识的任何评论或问题。 第2部分很快就会发布。
参考: java.lang.NoClassDefFoundError:如何解决–第1部分来自我们的JCG合作伙伴 Pierre-Hugues Charbonneau,位于Java EE支持模式和Java教程博客。
翻译自: https://www.javacodegeeks.com/2012/06/javalangnoclassdeffounderror-how-to.html