NoClassDefFoundError的可能原因

问题描述 投票:0回答:6

我得到以下内容

NoClassDefFoundError
,这很奇怪,因为该类已经存在于库 jar 中。

Exception in thread "main" java.lang.NoClassDefFoundError: abc/test/Test.java
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:795)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:144)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:382)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:75)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:294)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:288)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:287)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:327)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:795)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:144)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:382)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:75)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:294)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:288)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:287)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:327)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:432)
Caused by: java.lang.ClassNotFoundException: abc.test.Test
        at java.net.URLClassLoader$1.run(URLClassLoader.java:299)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:288)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:287)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:327)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 25 more

这看起来像是无法找到导致异常的同一个类。 我还在ant

build.xml
中包含了库路径,可以在下面验证。

<property name="deps" value="${lib}/abclib/abclib-test.jar"/>

<target name="dist" depends="compile">
        <manifest file="${dist}/MANIFEST.MF">
            <attribute name="Main-Class" value="xyz.test.TestConfiguration" />
            <attribute name="Class-Path" value="${deps}"/>
        </manifest>
        <jar jarfile="${dist}/abc.jar" basedir="${build}/" manifest="${dist}/MANIFEST.MF" />
</target>

我迷路了,有人至少可以指导我应该看哪里,或者我可能做错了什么吗?

另外,有人可以从堆栈跟踪中抛出一盏灯,

Exception
Caused by
。我不太明白他们两个有什么关系。

java ant build jar
6个回答
8
投票

使用函数初始化静态字段可能会导致难以揭开

NoClassDefFoundError

示例:当您执行以下操作时:

public class SomePanel extends Panel {
    static int CALC_VALUE = ValueCalcUtils.calcValue();
    ...

...哪里

ValueCalcUtils.calcValue()

...抛出异常。

然后,当抛出异常时,会发生以下情况:

  1. 将会有一个错误指示实际问题
    ValueCalcUtils.calcValue()
    由于某种原因引发了异常)
  2. 随后每次尝试创建
    SomePanel
    的实例都会抛出一个(误导性的)
    NoClassDefFoundError
    表示
    SomePanel

发生这种情况是因为 JVM 会记住

SomePanel
第一次尝试创建类定义时无法初始化,因此当再次询问时,
NoClassDefFoundError
“没有类定义”(
SomePanel
)。

在 Wicket/Tomcat 情况下...

我在 Tomcat Web 服务器上的 Wicket 应用程序中遇到了这个问题。问题是,静态 Utils-Method 依赖于

WicketApplication.get()

在大多数情况下,当 Tomcat 尝试在启动时从 SessionStore 恢复旧会话时,会导致所描述的问题。有时,会议包含相关面板的序列化实例。初始化面板类时出现异常,因为 Tomcat 启动时 WicketApplication 尚不存在。 后来,我们的应用程序日志中出现了很多令人困惑的面板

NoClassDefFoundError
,没有明显的原因。

我们终于在 tomcat-stderror.log 文件中找到了“root Error”的单一出现,因为它是 tomcat 在启动时抛出的初始错误。

希望这对某人有帮助。


6
投票

在另一个

SO条目
中对
NoClassDefFoundError
ClassNotFoundException之间的区别有一个很好的解释:

并不意味着...类不在 CLASSPATH 中。事实上恰恰相反。这意味着类...是由类加载器找到的,但是在尝试加载类时,读取类定义时遇到错误。当相关类具有使用类加载器未找到的类的静态块或成员时,通常会发生这种情况。因此,要找到罪魁祸首,请查看相关类的源代码...并查找使用静态块或静态成员的代码。

您需要查看 Test.java 的代码并找出它导入的内容,并确保这些类位于类路径中。 如果您需要帮助跟踪类,您可以发布 Test.java 的代码。


1
投票

ClassNotFoundException
NoClassDefFoundError
之间有区别..

first
则表示您正在使用的
class
不在您的
classpath

Second
一个表示,您正在使用的
class
又使用另一个不在您的类路径中的
class
..

所以,问题不在于你的类在类路径中没有。但问题是,你的类所依赖的

classes
不在你的类路径中。 现在,您需要检查所有
classes
,您的
class
(代码中当前使用的)取决于什么..


1
投票

Class-Path
中的
MANIFEST.MF
条目具有特定的格式,特别是类路径中的条目必须是相对URI(相对于包含清单的JAR的位置)。 Ant 有一个
manifestclasspath
任务
来帮助构建合适的类路径。

<target name="dist" depends="compile">
    <property name="jar.location" location="${dist}/mcon.jar"/>
    <manifestclasspath property="manifest.class.path" jarfile="${jar.location}">
      <classpath>
        <pathelement location="${deps}" />
      </classpath>
    </manifestclasspath>
    <manifest file="${dist}/MANIFEST.MF">
        <attribute name="Main-Class" value="xyz.test.TestConfiguration" />
        <attribute name="Class-Path" value="${manifest.class.path}"/>
    </manifest>
    <jar jarfile="${jar.location}" basedir="${build}/" manifest="${dist}/MANIFEST.MF" />
</target>

这应该使用正确的格式设置

Class-Path
(大概类似于您的示例中的
../lib/abclib/abclib-test.jar


0
投票

NoClassDefFoundError 意味着该类在编译期间存在,而不是在运行时执行期间存在。因此,正如其他人所建议的,您需要了解在运行时而不是在编译时使用的类路径。


0
投票
由于类加载器无法加载类的定义而抛出

NoClassDefFoundError
。确保给出类路径上的类的正确路径。检查该库是否位于类路径中。修改您
MANIFEST.MF
以便在
Class-Path
中存在一个库。使用命令行 -cp 开关运行 java 以表示类路径上的库。

© www.soinside.com 2019 - 2024. All rights reserved.