java ClassNotFoundException 与 NoClassDefFoundError

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28322833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:23:40  来源:igfitidea点击:

ClassNotFoundException vs NoClassDefFoundError

javaexceptionnoclassdeffounderrorclassnotfoundexception

提问by Deen John

I have gone through this thread What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException?This is what one of the ans,which has max ups, in thread is : NoClassDefFoundError:"So, it appears that the NoClassDefFoundError occurs when the source was successfully compiled, but at runtime, the required class files were not found. This may be something that can happen in the distribution or production of JAR files, where not all the required class files were included."

我已经浏览过这个线程NoClassDefFoundError 和 ClassNotFoundException 之间的原因和区别是什么?这是线程中具有最大 ups 的 ans 之一是: NoClassDefFoundError:"所以,似乎在成功编译源时发生了 NoClassDefFoundError ,但在运行时却找不到所需的类文件。这可能是在 JAR 文件的分发或生产中可能发生的事情,其中​​未包含所有必需的类文件。”

ClassNotFoundException: As for ClassNotFoundException, it appears that it may stem from trying to make reflective calls to classes at runtime, but the classes the program is trying to call is does not exist.

ClassNotFoundException:至于 ClassNotFoundException,它似乎源于尝试在运行时对类进行反射调用,但程序试图调用的类并不存在。

I did a small experiment . I created a main class, class Aand tried to call other class, class Bfrom it , compiled successfully.

我做了一个小实验。我创建了一个主类A 类并尝试从中调用其他类B类,编译成功。

Then i deleted the class B which is being called in class A. I got the java.lang.ClassNotFoundExceptionbut as per the answer in the tread, i should have got NoClassDefFoundError (source was compiled succesfully but at runtime class files were not found) Could anyone explain what am i missing in the interpretation of the ans in the thread ?

然后我删除了在 A 类中调用的 B 类。我得到了 java.lang.ClassNotFoundException,但根据步骤中的答案,我应该得到 NoClassDefFoundError(源已成功编译,但在运行时未找到类文件)谁能解释我在对线程中的 ans 的解释中遗漏了什么?

package com.random;

public class A {

    public static void main(String[] args) {
        B b= new B();

    }

}

 package com.random;

public class B {



}

采纳答案by Jean-Fran?ois Savard

NoClassDefFoundError

NoClassDefFoundError

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.

The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.

如果 Java 虚拟机或 ClassLoader 实例尝试加载类的定义(作为正常方法调用的一部分或作为使用 new 表达式创建新实例的一部分)并且找不到类的定义,则抛出。

编译当前正在执行的类时,搜索到的类定义存在,但无法再找到该定义。



ClassNotFoundException

类未找到异常

Thrown when an application tries to load in a class through its string name using: The forName method in class Class. The findSystemClass method in class ClassLoader . The loadClass method in class ClassLoader.

当应用程序尝试通过其字符串名称加载类时抛出:类 Class 中的 forName 方法。ClassLoader 类中的 findSystemClass 方法。ClassLoader 类中的 loadClass 方法。



You have to understand that the JVMcan't realize the definition of the classyou deleted can't be found, as the classitself can't be found which automatically throw the ClassNotFoundException.

你要明白,JVM无法实现class你删除的定义是找不到的,因为class找不到它本身,它会自动抛出ClassNotFoundException.

This exception happen at runtimeso it does not matter if it compiled first or not, you deleted the file, therefore it can't be found and throw the exception.

这个异常发生在runtime所以不管它是否先编译,你删除了文件,因此无法找到它并抛出exception.

Note that NoClassDefFoundErroris not actually an exception, it is an Errorderived from LinkageErrorwhile ClassNotFoundExceptionderive directly from java.lang.Exception.

请注意,这NoClassDefFoundError实际上并不是一个例外,它是ErrorLinkageErrorwhileClassNotFoundException直接派生自 的派生java.lang.Exception

To resume, the NoClassDefFoundErrorglobally simply mean that the JVMtried to access at runtimesomething that according to the compiledcode should exists, but does not actually exist (or is not in the classpath).

恢复,NoClassDefFoundError全局仅意味着JVM尝试访问runtime根据compiled代码应该存在但实际上不存在(或不在类路径中)的东西。



Example to reproduce ClassNotFoundException

重现 ClassNotFoundException 的示例

public class ClassNotFoundExceptionExample {

    private static final String CLASS_TO_LOAD = "main.java.Utils";

    public static void main(String[] args) {
        try {
            Class loadedClass = Class.forName(CLASS_TO_LOAD);
            System.out.println("Class " + loadedClass + " found successfully!");
        }
        catch (ClassNotFoundException ex) {
            System.err.println("A ClassNotFoundException was caught: " + ex.getMessage());
            ex.printStackTrace();
        }
    }
}


Example to reproduce NoClassDefFoundError

重现 NoClassDefFoundError 的示例

Create a simple class Test

创建一个简单的类 Test

public class Test {
        public Test() {
                System.out.println("A new instance of the Test class was created!");
        }
}

And a class NoClassDefFoundErrorExample

还有一个班 NoClassDefFoundErrorExample

public class NoClassDefFoundErrorExample {
        private static Test test = new Test();

        public static void main(String[] args) {
                System.out.println("The definition of Test was found!");
        }
}

Now create a n executable .jarwhich execute the mainmethod. You can specify it in the Manifest.txtfile inside the .jar

现在创建一个可执行.jarmain方法的可执行文件。你可以在Manifest.txt里面的文件中指定它.jar

Main-Class: NoClassDefFoundErrorExample

Now run the following commands

现在运行以下命令

javac Test.java
javac NoClassDefFoundErrorExample.java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
java -jar NoClassDefFoundErrorExample.jar

Notice the NoClassDefFoundError

请注意 NoClassDefFoundError

Exception in thread "main" java.lang.NoClassDefFoundError: TestClass
    at NoClassDefFoundErrorExample.(NoClassDefFoundErrorExample.java:2)
Caused by: java.lang.ClassNotFoundException: TestClass
    at java.net.URLClassLoader.run(URLClassLoader.java:372)
    at java.net.URLClassLoader.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

回答by Sarvesh Kumar Singh

Well... ClassNotFoundExceptionoccurs when the runtime is trying to find the class named by some Stringfor example Class.forName(java.lang.String)method take a string argument and tries to find the class with this name. In this case the class-name is a sting and can only be checked at runtime. here the exception clearly says... this "class" is not found. So... it can happen for two reasons :

好吧...ClassNotFoundException发生在运行时试图查找由某些String示例命名的类时,例如Class.forName(java.lang.String)采用字符串参数并尝试查找具有此名称的类。在这种情况下,类名是一个刺,只能在运行时检查。这里的异常清楚地表明......没有找到这个“类”。所以......这可能有两个原因:

Reason 1. Class-name is not a valid java-class ( example - "java.bang.kiting").

原因 1. 类名不是有效的 java 类(例如 - “java.bang.kiting”)。

// Example    
Class cdef = Class.forName( "java.bang.kiting" );

Reason 2. Class-name is was a valid class... but somehow it was not packaged with the jar or is not resolved in class-path. So as far as the runtime knows... it can be a wrong class name... similar to case 1.

原因 2. 类名是一个有效的类......但不知何故它没有与 jar 一起打包或没有在类路径中解析。所以就运行时所知......它可能是一个错误的类名......类似于情况1。

// Example    
Class cdef =Class.forName( "apache.some.SomeLegitClass" );

Where as NoClassDefFoundErrorfor cases where the actual class reference was used,

至于NoClassDefFoundError使用实际类引用的情况,

// example
import apache.some.SomeLegitClass
SomeLegitClass i = (SomeLegitClass) instanceOfSomeLegitClass;

So basically the everything was correct but somehow the class is not packaged with the jar ( or more generally - is not resolved in the class-path ). In this case we get NoClassDefFoundError.

所以基本上一切都是正确的,但不知何故该类没有与 jar 一起打包(或者更一般地说 - 没有在 class-path 中解析)。在这种情况下,我们得到NoClassDefFoundError.

Here runtime knows that the class is valid since it compiled successfully... but it can not find the "class definition".

这里运行时知道该类是有效的,因为它编译成功......但它找不到“类定义”。

回答by Crazyjavahacking

The difference depends on who asked the class to be loaded:

差异取决于谁问的类加载

  • ClassNotFoundExceptionis thrown when the code is directly trying to load a class, passing the Stringargument representing a Fully Qualified Name of the class.
    • e.g. Class.forName(String), or ClassLoader.loadClass(String).
  • NoClassDefFoundErroris thrown when the JVM is asked to load a class indirectly.
    • e.g. when class A is using class B and class B is not on classpath, NoClassDefFoundErrorwill be thrown.
  • ClassNotFoundException当代码直接尝试加载类时抛出,传递String表示类的完全限定名称的参数。
    • 例如Class.forName(String),或ClassLoader.loadClass(String)
  • NoClassDefFoundError当要求 JVM 间接加载类时抛出
    • 例如,当 A 类使用 B 类而 B 类不在类路径上时,NoClassDefFoundError将被抛出。

回答by Jeremy

NoClassDefFoundErroris usually called when you are using a library(for example, Guava, Gson, CommonsIO). You put the library in classpath of your project, but you didn't export it together, you will get a NoClassDefFoundErrorwhen the application is running.

NoClassDefFoundError通常在您使用库(例如 Guava、Gson、CommonsIO)时调用。您将库放在项目的类路径中,但您没有将其一起导出,NoClassDefFoundError当应用程序运行时您会得到一个。

How to get NoClassDefFoundError:
Create a new project, with this class.

如何获得NoClassDefFoundError
用这个类创建一个新项目。

public class A
{
    public void do()
    {
        System.out.println("Do!");
    }
}  

Export it as a .jarfile.

将其导出为.jar文件。

Now create another project. Add the exported jar file to classpath.

现在创建另一个项目。将导出的 jar 文件添加到类路径。

import ???.A;
public class Main
{
    public static void main(String[] args)
    {
        A a = new A();
        a.do();//NoClassDefFoundError thrown at here.
    }
} 

Export the project, make sure you do not include the jar file(with class A). Run the newly exported jar file, you will see that error!

导出项目,确保不包含 jar 文件(带有 class A)。运行新导出的jar文件,你会看到那个错误!

回答by Rohit Gaikwad

1)ClassNotFoundException

1) ClassNotFoundException

  1. This occurs, when we try to load a class at run-time using Class.forName()or ClassLoader.loadClass()or ClassLoader.findSystemClass()methods and it could notfind the required class in the class path.
  2. In this case, we should check the class pathand add the class in the class path if it is missing.
  3. This is a checked Exception, which is derived from java.lang.Exceptionclass .
  4. This comes under explicitloading.
  1. 出现这种情况,当我们试图通过加载在运行时类Class.forName()ClassLoader.loadClass()ClassLoader.findSystemClass()方法,它可能无法找到在所需的类的类路径
  2. 在这种情况下,我们应该检查class path并在类路径中添加该类,如果它丢失了。
  3. 这是一个受检异常,它派生自java.lang.Exception类。
  4. 这属于显式加载。

2)NoClassDefFoundError

2) NoClassDefFoundError

  1. This occurs, when the class was present during the compile timeand is not available during run timefor some reasons. It means the class which is getting loaded is presentin classpath, but one of the dependent classe(s)which are required by this class are either removedor failedto load by the compiler.

  2. In this case, we only need to check the classes which are dependent on this class.

  3. This is an Error, which is derived from java.lang.LinkageError.
  4. This comes under implicitloading.
  1. 发生这种情况时,该类在 期间存在compile time并且run time由于某些原因在期间不可用。这意味着正在加载的类present在 中classpath,但classe(s)此类所需的依赖项之一已被删除无法被编译器加载。

  2. 在这种情况下,我们只需要检查classes which are dependent on this class.

  3. 这是一个Error,它派生自java.lang.LinkageError
  4. 这属于隐式加载。

回答by IamVickyAV

As mentioned in previous answers, NoClassDefFoundError will occur when the class was present during the compile time and is not available during run time for some reasons.

正如前面的答案中提到的,当类在编译时存在并且由于某些原因在运行时不可用时,将发生 NoClassDefFoundError。

There is another scenario I wish to add, which could also result in NoClassDefFoundError.

我想添加另一个场景,它也可能导致 NoClassDefFoundError。

When you are trying to load a class which failed to load due to some exception say failure in static initialization block, system will throw you ExceptionInInitializerError. If you try to load the same class again (which failed to load previously), system will throw NoClassDefFoundError

当您尝试加载由于某些异常而无法加载的类时,例如静态初始化块中的失败,系统将向您抛出 ExceptionInInitializerError。如果您再次尝试加载同一个类(之前加载失败),系统将抛出 NoClassDefFoundError

Lets explore it with an sample

让我们用一个例子来探索它

ClassWithStaticBlock.java

ClassWithStaticBlock.java

public class ClassWithStaticBlock {

    static {
       int total = 1/0;
    }
}

Main.java

主程序

public class Main {

public static void main(String[] args) {
    ClassWithStaticBlock cs;
    try {
       cs = new ClassWithStaticBlock();
    }catch(Throwable e){
        e.printStackTrace();
    }
  }
}

Result:

结果:

java.lang.ExceptionInInitializerError
    at Main.main(Main.java:6)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ArithmeticException: / by zero
    at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.java:7)
    ... 6 more

Lets modify Main.java

让我们修改Main.java

public class Main {

    public static void main(String[] args) {
        ClassWithStaticBlock cs;
        try {
           cs = new ClassWithStaticBlock();
        }catch(Throwable e){
            e.printStackTrace();
        }
        cs = new ClassWithStaticBlock(); //try to use ClassWithStaticBlock again
    }
}

Result:

结果:

java.lang.ExceptionInInitializerError
    at Main.main(Main.java:6)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ArithmeticException: / by zero
    at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.java:7)
    ... 6 more
Exception in thread "Main Thread" java.lang.NoClassDefFoundError: ClassWithStaticBlock
    at Main.main(Main.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

When we try to use ClassWithStaticBlock again (which failed to initialize earlier), System is throwing NoClassDefFoundError.

当我们再次尝试使用 ClassWithStaticBlock(之前初始化失败)时,系统抛出 NoClassDefFoundError。

Found the sample from Why am I getting a NoClassDefFoundError in Java?

为什么我在 Java 中得到 NoClassDefFoundError 中找到示例

回答by Naresh Joshi

Everything About ClassNotFoundException Vs NoClassDefFoundErrorarticle explains the difference between ClassNotFoundException Vs NoClassDefFoundError very clearly with example and according to it.

关于 ClassNotFoundException Vs NoClassDefFoundError 的一切文章通过示例和根据它非常清楚地解释了 ClassNotFoundException 与 NoClassDefFoundError 之间的区别。

ClassNotFoundException Vs NoClassDefFoundError -- Programming Mitra

ClassNotFoundException 与 NoClassDefFoundError — 编程 Mitra

ClassNotFoundException

类未找到异常

Is a checked exception that occurs when we tell JVM to load a class by its string name using Class.forName() or ClassLoader.findSystemClass() or ClassLoader.loadClass() methods and mentioned class is not found in the classpath.

当我们使用 Class.forName() 或 ClassLoader.findSystemClass() 或 ClassLoader.loadClass() 方法告诉 JVM 通过其字符串名称加载类时发生的已检查异常,并且在类路径中找不到提到的类。

Most of the time, this exception occurs when you try to run an application without updating the classpath with required JAR files. For Example, You may have seen this exception when doing the JDBC code to connect to your database i.e.MySQL but your classpath does not have the jar for it.

大多数情况下,当您尝试运行应用程序而不使用所需的 JAR 文件更新类路径时,会发生此异常。例如,在执行 JDBC 代码以连接到您的数据库 ieMySQL 时,您可能已经看到此异常,但您的类路径没有它的 jar。

public class Test {
    public static void main(String[] args) throws Exception {

        // Provide any class name to Class.forName() which does not exist
        // Or compile Test.java and then manually delete Person.class file so Person class will become unavailable
        // Run the program using java Test

        Class clazz = Class.forName("Person");
        Person person = (Person) clazz.newInstance();
        person.saySomething();
    }
}

class Person {
    void saySomething() {
        System.out.println("Hello");
    }
}

NoClassDefFoundError

NoClassDefFoundError

Is a subtype of java.lang.Error and Error class indicates an abnormal behavior which really should not happen with an application but and application developers should not try to catch it, it is there for JVM use only.

是 java.lang.Error 的子类型,Error 类表示应用程序不应该发生的异常行为,但应用程序开发人员不应试图捕捉它,它仅供 JVM 使用。

NoClassDefFoundError occurs when JVM tries to load a particular class that is the part of your code execution (as part of a normal method call or as part of creating an instance using the new keyword) and that class is not present in your classpath but was present at compile time because in order to execute your program you need to compile it and if you are trying use a class which is not present compiler will raise compilation error.

NoClassDefFoundError 当 JVM 尝试加载作为代码执行一部分的特定类(作为正常方法调用的一部分或作为使用 new 关键字创建实例的一部分)并且该类不存在于您的类路径中但存在时,就会发生 NoClassDefFoundError在编译时,因为为了执行您的程序,您需要编译它,如果您尝试使用不存在的类,编译器将引发编译错误。

public class Test {
    public static void main(String[] args) throws Exception {

        // Do javac on Test.java, 
        // Program will compile successfully because Empoyee class exits
        // Manually delete Employee.class file
        // Run the program using java Test
        Employee emp = new Employee();
        emp.saySomething();

    }
}

class Employee {
    void saySomething() {
        System.out.println("Hello");
    }
}

回答by Ajit Lakhwani

One of cases where NoClassDefFoundError occur is when the Class JVM is trying to access is not found in classpath. But if class is present in classpath, It will result in ClassNotFoundException.

发生 NoClassDefFoundError 的情况之一是在类路径中找不到 JVM 尝试访问的类。但是如果类存在于类路径中,则会导致 ClassNotFoundException。

In short NoClassDefFoundError will come if a class was present during compile time but not available in java classpath during runtime.

简而言之,如果一个类在编译时存在但在运行时在 java 类路径中不可用,则会出现 NoClassDefFoundError。

Just try to run with explicit -classpath option where the classpath does not contain class B.

只需尝试使用显式 -classpath 选项运行,其中类路径不包含 B 类。

回答by Nils-Erik

The other answers in this thread are correct, i just want to add something i spent hours trying to figure out. Even if

该线程中的其他答案是正确的,我只想添加一些我花了几个小时试图弄清楚的东西。即使

Class.forName("apache.some.SomeLegitClass")

works,

作品,

Class.forName("apache.some.somelegitclass")

will result in a NoClassDefFoundError. The Class.forName() is case-sensitive. It will result in different exceptions if the classname is spelled wrong, or simply has incorrect casing.

将导致 NoClassDefFoundError。Class.forName() 区分大小写。如果类名拼写错误,或者只是大小写不正确,则会导致不同的异常。