NoClassDefFoundError的可能原因

时间:2012-09-26 16:40:01

标签: java ant build jar

我得到以下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>

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

此外,有人可以抛光,“例外”和“引起”。我不太了解他们两人有什么关系。

6 个答案:

答案 0 :(得分:5)

对另一个SO entryNoClassDefFoundErrorClassNotFoundException之间的区别有一个非常好的解释:

  

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

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

答案 1 :(得分:4)

使用可能抛出异常的函数初始化静态字段可能导致难以解释NoClassDefFoundError

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

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

...其中

ValueCalcUtils.calcValue()

...可能会抛出异常。

然后,当抛出异常时,会发生这种情况:

  1. 在实际问题上会出现一个错误(由于某种原因,ValueCalcUtils.calcValue()已抛出异常)
  2. 每次创建SomePanel实例的后续尝试都会为NoClassDefFoundError抛出(误导性)SomePanel
  3. 发生这种情况是因为JVM会记住在他第一次尝试创建类定义时无法初始化SomePanel,因此{没有类定义“(NoClassDefFoundError) {1}}再次被问到。

    在Wicket / Tomcat情况下......

    我在Tomcat-Webserver上遇到了Wicket-Application的确切问题。问题是,静态Utils-Method依赖于SomePanel

    在大多数情况下,这将起作用,当Tomcat尝试在启动时从SessionStore恢复旧的Sessions时,它将导致所描述的问题。有时,会话包含问题小组的序列化实例。初始化Panel-Class时出现异常,因为Tomcat启动时尚未存在 WicketApplication 。 后来我们在应用程序日志中对Panel进行了很多混乱WicketApplication.get(),没有明显的原因。

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

    希望这有助于某人。

答案 2 :(得分:1)

ClassNotFoundExceptionNoClassDefFoundError之间存在差异..

虽然first一个表示您使用的class不在classpath

Second一个表示,您使用的class依次使用的不在您的类路径中的class ..

所以,问题不在于你没有在classpath中拥有你的类..但问题是,你的类所依赖的classes不在你的类路径中。 现在,您需要检查所有classesclass(代码中当前使用的那个)取决于... {/ p>

答案 3 :(得分:1)

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

<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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

因为你的类加载器无法加载类的定义而抛出

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