【问题标题】:Possible reasons for NoClassDefFoundErrorNoClassDefFoundError 的可能原因
【发布时间】:2012-09-18 08:37:21
【问题描述】:

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

这看起来无法找到导致异常的同一个类。 我还在 antbuild.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>

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

另外,有人可以抛出“异常”和“原因”。我不太明白他们两个有什么关系。

【问题讨论】:

  • 如何开始您的应用程序?您能否将完整的控制台命令添加到您的问题中?
  • 你是如何运行它的? (命令、目录树中的位置等)您得到abc/test/test.java 文本可能会很有趣。
  • lib 属性的值是多少?为了在清单类路径中使用,它需要是相对路径(使用正斜杠),相对于主 JAR 文件的位置,而不是绝对路径(就像您从 &lt;property name="lib" location="lib"/&gt; 获得的那样)。我建议您考虑使用manifestclasspath 任务将您的依赖类路径转换为正确的格式,以便在清单中使用。
  • @Andreas_D- 我正在使用带有一些其他参数的“java -jar mcon.jar”。另外,我正在从项目的根目录运行它。
  • @DaveNewton- 我已经更改了问题的类和包名称。它与“abc.test.Test”的类相同

标签: java ant build jar


【解决方案1】:

ClassNotFoundException 和 NoClassDefFoundError 之间有区别..

而first 表示您使用的class 不在您的classpath 中

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

所以,问题不在于您的类路径中没有您的类。但问题是,您的类所依赖的 classes 不在您的类路径中。 现在,您需要检查所有classes,您的class(当前在您的代码中使用的那个)依赖于什么......

【讨论】:

  • 我的主类依赖于库中的abc.test.Test 类,并且我已将该库包含在我的类路径中。
  • 你的abc.test.Test 类是否依赖于任何其他类?您还需要将它们添加到library。
  • 库中的上述类,根据错误,它无法找到导致异常的同一类。
  • 实际上我不能给你更多有价值的输入,因为你正在使用Ant构建文件。我实际上不知道如何通过Ant构建文件搜索一个类。对不起..可能你可以看看其他成员的答案..
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    NoClassDefFoundError 抛出,因为您的类加载器无法加载类的定义。确保给出了类路径上的类的正确路径。检查库是否在类路径中。修改您的MANIFEST.MF,使Class-Path 中存在一个库。使用命令行 -cp 开关运行 java 以表示类路径上的库。

    【讨论】:

    • 我尝试将-cp 与绝对类路径一起使用,但仍然遇到相同的错误。
    【解决方案4】:

    MANIFEST.MF 中的 Class-Path 条目具有特定格式,特别是类路径中的条目必须是相对 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)

    【讨论】:

      【解决方案5】:

      在另一个SO entry 中对NoClassDefFoundError 和ClassNotFoundException 之间的区别有一个非常好的解释:

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

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

      【讨论】:

      • 谢谢,可能是这个原因,我去看看源代码。
      【解决方案6】:

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

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

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

      ...哪里

      ValueCalcUtils.calcValue()
      

      ...抛出异常。

      那么,当抛出异常时,就会发生这种情况:

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

      发生这种情况是因为 JVM 会记住 SomePanel 在他第一次尝试创建类定义时无法初始化,因此当被问及 SomePanel 时“没有类定义”(NoClassDefFoundError)再次。

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

      我在 Tomcat-Webserver 上的 Wicket-Application 遇到了这个确切的问题。问题是,静态 Utils-Method 依赖于WicketApplication.get()。

      这在大多数情况下都有效,但当 Tomcat 在启动时尝试从 SessionStore 恢复旧 Session 时,它会导致所描述的问题。有时,会议包含相关小组的序列化实例。初始化 Panel-Class 时出现异常,因为 WicketApplication 在 Tomcat 启动时尚不存在。 后来,我们的应用程序日志中的面板有很多令人困惑的NoClassDefFoundErrors,没有明显的原因。

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

      希望这对某人有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-13
        • 2010-09-13
        • 2013-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多