是什么导致NoSuchMethodError和NoClassDefFoundError?

时间:2012-02-09 07:50:58

标签: java classpath noclassdeffounderror nosuchmethoderror

当我运行test.class时,我收到以下错误:

Exception in thread "main" java.lang.NoSuchMethodError: ml.Temp.<init>(Ljava/lang/String;II)V
    at test.main(test.java:11)

这是test.java的代码

import java.io.*;
import ml.*;

class test
{
        public static void main(String[] args) throws FileNotFoundException, IOException
        {
                String filename = "input";

                Temp id = new Temp(filename, 6, 100);
                    id.someFunction();          
         }
}

基本上我有一个包含Temp.class的jar文件(Temp是我写的一个库文件,它位于ml包下面)。 Temp有一个构造函数,它接受这三个参数和一个公共someFunction。

不确定这是否有帮助,但我在编译期间包含了jar文件的类路径。当我在test.class运行期间包含jar文件的类路径时,我得到以下内容

Exception in thread "main" java.lang.NoClassDefFoundError: test
Caused by: java.lang.ClassNotFoundException: test
    at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
Could not find the main class: test. Program will exit.

编辑:

如果有帮助我编译如下(ml.jar和test.java在同一目录中)

javac -cp ml.jar test.java

3 个答案:

答案 0 :(得分:1)

您应该从java -cp <path-to-ml.jar> test所在的路径运行命令test.class

修改

NoSuchMethodError表示在课程test的第11行中,您尝试使用带有签名的ml.ID3(不是Temp!)的构造函数({{ 1}})不存在。这并不意味着它不在类路径中,因为这会导致String, int, int

另一方面,NoClassDefFoundError表示NoClassDefFoundError: test不再位于您的clss路径中。将jar添加到类路径中,如果你真的这样做了test不能导致NoClassDefFoundError: test从你的类路径中消失......所以它更有可能你已经做了一些其他无意的行动。

编辑2

也许构造函数存在于开发环境中使用的test中,但显然在运行时环境中不存在。如果它是第三方jat,可能会发生这个jar的两个版本,一个在dev中使用,另一个在运行时使用。或者甚至可能两者都出现在您的运行时环境中,但缺少该构造函数工具的优先级。

答案 1 :(得分:1)

很难告诉你没有源代码发生了什么,但看起来你的库和正在使用它的项目是不同步的。您是否更改了库/项目中任何方法的签名?我建议重新编译所有内容,然后检查类test是否正在使用您已重新编译的库的最新版本以及它是否已声明public

有关如何阅读NoSuchMethodError等的更多有用信息,请参阅此处的精彩文章:http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/

答案 2 :(得分:1)

我打算假装成你并完成整个过程:

1 - 图书馆。我在一个名为workspace的目录中。在其中,我创建了一个名为ml的目录。
ml目录中,我创建了一个名为Temp.java的新文件,为了举例,它包含以下内容:

package ml;

public class Temp
{
    public Temp(String filename, int arg1, int arg2)
    {
        //do something
    }

    public void someFunction()
    {
        //do something else
        System.out.println("look left!");
    }
}

我现在要编译库类并创建一个库jar。 首先我通过运行

进行编译
javac ./Temp.java

ml目录中。然后我通过将一个目录放到workspace目录并运行:

来对库进行jar操作
jar cf ml.jar ml/

2 - 该计划。我现在在Test.java目录中创建workspace文件。该文件包含以下内容:

import java.io.*;
import ml.*;

public class Test
{
    public static void main(String[] args) throws FileNotFoundException, IOException
    {
        String filename = "input";

        Temp id = new Temp(filename, 6, 100);
        id.someFunction();
    }
}

3 - 结果。我现在继续编译并运行我的测试程序。在我运行的workspace目录中:

javac -cp ./:ml.jar ./Test.java

我最终可以通过在workspace目录中运行以下命令来运行程序:

java -cp ./:ml.jar Test

将显示输出:

look left!

我希望这会有所帮助。