欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

java.lang.NoClassDefFoundError:如何解决–第2部分

发布时间:2023/12/3 34 豆豆
生活随笔 收集整理的这篇文章主要介绍了 java.lang.NoClassDefFoundError:如何解决–第2部分 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
本文是我们的NoClassDefFoundError故障排除系列的第2部分。 看一下第1部分 。 它将重点介绍最简单的NoClassDefFoundError问题类型。 本文对于Java初学者来说是理想的选择,我强烈建议您自己编译并运行示例Java程序。

今后将使用以下书写格式,并为您提供:
–问题案例的描述和NoClassDefFoundError的类型
–示例Java程序“模拟”问题情况 – ClassLoader链视图 –建议和解决策略

NoClassDefFoundError问题案例1 –缺少JAR文件

我们将介绍的第一个问题案例与Java程序包装和/或类路径问题有关。 典型的Java程序可以包含一个或多个在编译时创建的JAR文件。 当您忘记添加包含Java或Java EE应用程序引用的Java类的JAR文件时,通常会观察到NoClassDefFoundError。

一旦您分析了Java异常并缺少Java类名,通常就不难解决这种类型的问题。

示例Java程序

以下简单的Java程序按以下方式拆分:
–主Java程序NoClassDefFoundErrorSimulator
–调用者Java类CallerClassA –引用Java类ReferencingClassA –用于ClassLoader和日志记录相关设施的util类JavaEETrainingUtil

这个程序很简单,它试图创建一个新实例并执行一个Java类CallerClassA的方法,该方法引用了ReferencingClassA类。 它将演示一个简单的类路径问题如何触发NoClassDefFoundError。 该程序还在类加载时显示当前类加载器链的详细信息,以帮助您跟踪此过程。 当处理更大的类加载器链时,这对于将来和更复杂的问题案例特别有用。

package org.ph.javaee.training1;import org.ph.javaee.training.util.JavaEETrainingUtil;/*** NoClassDefFoundErrorTraining1* @author Pierre-Hugues Charbonneau**/ public class NoClassDefFoundErrorSimulator {/*** @param args*/public static void main(String[] args) {System.out.println("java.lang.NoClassDefFoundError Simulator - Training 1");System.out.println("Author: Pierre-Hugues Charbonneau");System.out.println("http://javaeesupportpatterns.blogspot.com");// Print current Classloader contextSystem.out.println("\nCurrent ClassLoader chain: "+JavaEETrainingUtil.getCurrentClassloaderDetail());// 1. Create a new instance of CallerClassACallerClassA caller = new CallerClassA();// 2. Execute method of the callercaller.doSomething();System.out.println("done!");} }package org.ph.javaee.training1;import org.ph.javaee.training.util.JavaEETrainingUtil;/*** CallerClassA* @author Pierre-Hugues Charbonneau**/ public class CallerClassA {private final static String CLAZZ = CallerClassA.class.getName();static {System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());}public CallerClassA() {System.out.println("Creating a new instance of "+CallerClassA.class.getName()+"...");}public void doSomething() {// Create a new instance of ReferencingClassAReferencingClassA referencingClass = new ReferencingClassA(); } }package org.ph.javaee.training1;import org.ph.javaee.training.util.JavaEETrainingUtil;/*** ReferencingClassA* @author Pierre-Hugues Charbonneau**/ public class ReferencingClassA {private final static String CLAZZ = ReferencingClassA.class.getName();static {System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());}public ReferencingClassA() {System.out.println("Creating a new instance of "+ReferencingClassA.class.getName()+"...");}public void doSomething() {//nothing to do...} }package org.ph.javaee.training.util;import java.util.Stack; import java.lang.ClassLoader;/*** JavaEETrainingUtil* @author Pierre-Hugues Charbonneau**/ public class JavaEETrainingUtil {/*** getCurrentClassloaderDetail* @return*/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 chainwhile (currentClassLoader != null) {classLoaderStack.push(currentClassLoader);currentClassLoader = currentClassLoader.getParent();}// Print ClassLoader parent chainwhile(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类ReferencingClassA的类路径中省略其中一个JAR文件。

Java程序的包装如下:
– MainProgram.jar(包含NoClassDefFoundErrorSimulator.class和JavaEETrainingUtil.class)
-CallerClassA.jar(包含CallerClassA.class) – ReferencingClassA.jar(包含ReferencingClassA.class)

现在,让我们按原样运行程序:

建议和解决策略

##基准(正常执行)

..\bin>java -classpath CallerClassA.jar;ReferencingClassA.jar;MainProgram.jar org.ph.javaee.training1.NoClassDefFoundErrorSimulatorjava.lang.NoClassDefFoundError Simulator - Training 1 Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.comCurrent ClassLoader chain: ----------------------------------------------------------------- sun.misc.Launcher$ExtClassLoader@17c1e333 --- delegation --- sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader** -----------------------------------------------------------------Classloading of org.ph.javaee.training1.CallerClassA in progress... ----------------------------------------------------------------- sun.misc.Launcher$ExtClassLoader@17c1e333 --- delegation --- sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader** -----------------------------------------------------------------Creating a new instance of org.ph.javaee.training1.CallerClassA... Classloading of org.ph.javaee.training1.ReferencingClassA in progress... ----------------------------------------------------------------- sun.misc.Launcher$ExtClassLoader@17c1e333 --- delegation --- sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader** -----------------------------------------------------------------Creating a new instance of org.ph.javaee.training1.ReferencingClassA... done!

发生了什么? 删除包含ReferencingClassA的ReferencingClassA.jar确实阻止了当前类加载器在运行时定位此引用Java类,从而导致ClassNotFoundException和NoClassDefFoundError。

如果您从Java启动类路径中或Java EE相关应用程序的EAR / WAR中省略JAR文件,这将是典型的异常。

ClassLoader视图

现在,让我们回顾一下ClassLoader链,以便您可以正确地了解这种问题情况。 从Java程序输出日志记录中可以看到,找到了以下Java ClassLoader:

Classloading of org.ph.javaee.training1.CallerClassA in progress... ----------------------------------------------------------------- sun.misc.Launcher$ExtClassLoader@17c1e333 --- delegation --- sun.misc.Launcher$AppClassLoader@214c4ac9 **Current ClassLoader** -----------------------------------------------------------------

**请注意,Java引导类加载器负责加载核心JDK类,并以本机代码编写**

## sun.misc.Launcher $ AppClassLoader

这是系统类加载器,负责加载在启动时指定的Java类路径中找到的应用程序代码。

## sun.misc.Launcher $ ExtClassLoader

这是扩展类加载器,负责将代码加载到扩展目录(<java_home> / lib / ext或java.ext.dirs系统属性指定的任何其他目录)中。

从Java程序日志输出中可以看到,扩展类加载器是系统类加载器的实际超级父级。 我们的示例Java程序是在系统类加载器级别加载的。 请注意,对于这种问题情况,该类加载器链非常简单,因为我们此时尚未创建子类加载器。 这将在以后的文章中介绍。

建议和解决策略

现在在下面找到我对NoClassDefFoundError问题案例1的建议和解决策略:

–检查java.lang.NoClassDefFoundError错误并确定缺少的Java类
-在编译/构建环境中验证并找到丢失的Java类
-确定缺少的Java类是来自应用程序代码,第三方API还是Java EE容器本身。 验证预期在哪里找到丢失的JAR文件 –找到后,验证您的运行时环境Java类路径是否存在任何拼写错误或丢失的JAR文件 –如果问题是由Java EE应用程序触发的,请执行与上述相同的步骤,但请验证EAR / WAR文件的包装是否缺少JAR和其他库文件依赖项(如MANIFEST)。

请随时发表任何问题或评论。 第3部分将很快上市。

参考: java.lang.NoClassDefFoundError:如何解决–第2部分,来自我们的JCG合作伙伴 Pierre-Hugues Charbonneau,位于Java EE支持模式和Java教程博客。


翻译自: https://www.javacodegeeks.com/2012/06/this-article-is-part-2-of-our.html

总结

以上是生活随笔为你收集整理的java.lang.NoClassDefFoundError:如何解决–第2部分的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。