【问题标题】:NoClassDefFoundError on an interface, not a class接口上的 NoClassDefFoundError,而不是类
【发布时间】:2011-10-03 13:50:39
【问题描述】:

我对@9​​87654322@ 有疑问。我正在使用接口,应该没有可用的类定义:

package code;
public interface Constants {...}

实现此接口的类编译没有任何错误,并且已经构建了一个 JAR 文件,但在运行时它给了我一个错误。

import ...;
import code.*;
public class MultiDoc extends LanguageAnalyser implements Constants{}

Constants 只包含一个常量列表。

我阅读了一些指向 CLASSPATH 作为导致此问题的原因的帖子,但我的 CLASSPATH 中有 code 包。如果我没有它,它会产生编译错误。所以,问题应该是别的。

运行时错误是:

java.lang.NoClassDefFoundError: code/Constants

解决办法是什么?

【问题讨论】:

  • The "Constants" only contains a list of constant variables. 那叫Constant Interface anti pattern :)
  • 那么,究竟什么是“常量变量”? ;)
  • @Daniel - 一个变量,javaDoc 告诉你:HANDS OFF ;)
  • @alef - 回滚标签更改 - 我被你的一个 cmets 弄糊涂了,以为 GATE 是某种使用 java 字节码的其他语言(比如 scala 左右)。现在我知道它只是一个用于 nlp 的 java 框架。 而且它有一个main方法!!

标签: java noclassdeffounderror


【解决方案1】:

检查这个类的静态初始化。看这里:what is the difference between NoClassDefFoundError and ClassNotFoundException
java.lang.NoClassDefFoundError: code/Constants 并不表示Constants 类不在CLASSPATH 中。事实上,情况恰恰相反。这意味着该类已被 ClassLoader 找到,但是 在尝试加载该类时,它在读取类定义时遇到了错误。这通常发生在所讨论的类具有使用 ClassLoader 未找到的类的静态块或成员时。

【讨论】:

  • 不,它不使用任何其他类,它只包含这样的常量列表: public static final String STFDPARSE_LINKPASLIST_FEATURE_NAME = "linkpaslist";
【解决方案2】:

请注意,有两个不同的异常听起来非常相似:ClassNotFoundException 和 NoClassDefFoundError。

第一个异常发生在JVM查找“packageB.ClassA”但在搜索路径中找不到它的简单情况下。我怀疑还有其他一些情况,但相当罕见。

第二个异常主要发生在找到一个适当命名的类文件,但由于某种原因它不能使用时。这主要有两个原因:

  1. 类位于,例如,“packageA/ClassA.class”,但内部命名为“packageB/ClassA”(或者包名在源代码中被意外省略,或者类文件位于错误的目录中,因为它包名)。
  2. 加载类时出现某种错误,通常是初始化静态存储时出错。

【讨论】:

    【解决方案3】:

    如果您的类路径中有somedirectory/code,那是错误。您总是需要类路径中的 base 目录(在本例中为somedirectory)。 Java 本身会在这些根目录中搜索一个名为 code 的目录,其中包含一个名为 Constants.class 的文件。

    【讨论】:

    • 正确,我在CLASSPATH中使用它的父级和显式jar文件地址
    【解决方案4】:

    编译时您可能会将它放在您的 CLASSPATH 中,但这并不能保证在您运行它时它就在 CLASSPATH 中。你是怎么运行的?

    【讨论】:

    • 查看 Andreas_D 的回答。实际上,对于 linux,您必须在 jar 之间添加一个冒号:java -cp /.../code-misc.jar:/.../MultiDoc.jar my.application.Main
    • 如果这不起作用,您应该检查您的 code-misc.jar 是否正确。编译用的是同一个jar吗?
    【解决方案5】:

    从您的问题中,我看到编译后的 Constants 接口位于一个与实现类的 jar/位置不同的 jar 中。所以你应该能够像这样执行你的应用程序:

    java -cp /path-to-jar/JarContainingConstants.jar my.application.Main
    

    (将姓名替换为您的真实姓名)

    If 您已将其他类添加到另一个 jar 并且 then if 您使该 jar 可执行并且 then if 您尝试运行它与java -jar MyApplication.jar, 然后 任何在执行的 jar 之外定义的类路径都将被忽略。但上述命令应该适用于任何 jar(可执行或不可执行)。


    来自评论

    [alef@localhost ~]$ java -cp /../code-misc.jar /.../MultiDoc.jar 
    Exception in thread "main" java.lang.NoClassDefFoundError: /.../MultiDoc/MultiDoc/jar 
    Caused by: java.lang.ClassNotFoundException: .home. 
      ... .MultiDocDateMathcer.jar 
      at java.net.URLClassLoader$1.run(URLClassLoader.java:217) 
      ... 
      at java.lang.ClassLoader.loadClass(ClassLoader.java:266) 
    Could not find the main class: /.../MultiDoc/MultiDocr.jar. 
    Program will exit.
    

    你的电话肯定是不正确的。这样做(更新):

    java -Dgate.home=/my/new/gate/home/directory -cp gate.jar;code-misc.jar;MultiDoc.jar gate.Main
    

    【讨论】:

    • 它在终端中给出了这个错误:[alef@localhost ~]$ java -cp /../code-misc.jar /.../MultiDoc.jar 线程“main”java中的异常。 lang.NoClassDefFoundError: /.../MultiDoc/MultiDoc/jar 原因:java.lang.ClassNotFoundException: .home。 ... .MultiDocDateMathcer.jar at java.net.URLClassLoader$1.run(URLClassLoader.java:217) ... at java.lang.ClassLoader.loadClass(ClassLoader.java:266) 找不到主类:/。 ../MultiDoc/MultiDocr.jar。程序将会退出。我的 CLASSPATH 中有那个 code-misc.jar,它包含具有 Constants.class 文件的代码包。
    • 实际上它不应该这样工作,我使用的是 GATE(一个 NLP 工具)并且它没有 main 函数,而不是 main 它有 execute() ,它在正常情况下完全作为 main 方法工作爪哇代码。 GATE 有自己的环境,以及自己的 gate.jar 文件,其中包含自己版本的 java 库 + 一些特定于 NLP 的编写库。它的工作方式类似于 JAVA 编辑器 GUI,但具有额外的 NLP 相关功能。我从 4 个月前开始使用它,它一直运行良好,但我之前从未尝试过接口。
    • @alef - 如果您以java 开头,那么您需要一个具有 main 方法的类。也许 GATE 框架提供了一个带有 main 方法的类,而您的贡献/插件提供了 execute() 方法。相信我,某处有一个main 方法。检查MultiDoc.jar里面的MANIFEST.MF文件,应该有一个指针。
    • 我认为 GATE 用自己的路径覆盖了 CLASSPATH,而忽略了我的环境变量。
    • 我找到了解决方案。我只是更改了 GATE build.xml 文件并在那里添加了我自己的环境 CLASSPATH 作为参数。谢谢你们:-)。
    【解决方案6】:

    任何接口都必须在类中声明。

    public class Calbacks {
        public interface IBaseFragmentInterface {
            void NotifyMainActivity();
        }
    }
    

    *我很早就找到了这个问题的解决方案,但我通过科学戳的方法独立找到解决方案

    【讨论】:

    • “任何接口都必须在类中声明。” - 这完全是错误的。
    • 是的,但在 android studio 2.4 中是真的!
    猜你喜欢
    • 2018-09-04
    • 2011-03-23
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    相关资源
    最近更新 更多