我已经完成了这个帖子What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException? 这是一个在线程中具有max ups的ans之一: NoClassDefFoundError :"因此,似乎在成功编译源时出现NoClassDefFoundError ,但在运行时,找不到所需的类文件。这可能是在分发或生成JAR文件时可能发生的事情,其中并未包含所有必需的类文件。"
ClassNotFoundException :对于ClassNotFoundException,它似乎源于尝试在运行时对类进行反射调用,但程序试图调用的类不存在。
我做了一个小实验。我创建了一个主类 A类,并试图从中调用其他类 B ,编译成功。
然后我删除了在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 {
}
答案 0 :(得分:13)
<强> NoClassDefFoundError的强>
如果Java虚拟机或ClassLoader实例尝试,则抛出该异常 加载类的定义(作为普通方法调用的一部分或 作为使用新表达式创建新实例的一部分)和否 可以找到班级的定义。
当前正在执行的搜索类定义存在 编译了类,但无法再找到定义。
<强> ClassNotFoundException的强>
当应用程序尝试通过其字符串加载类时抛出 name using:类Class中的forName方法。 findSystemClass ClassLoader类中的方法。类中的loadClass方法 类加载器。
您必须了解JVM
无法实现您删除的class
的定义无法找到,因为class
本身无法自动找到抛出ClassNotFoundException
。
此异常发生在runtime
,因此无论是否先编译都没关系,您删除了该文件,因此无法找到它并抛出exception
。
请注意,NoClassDefFoundError
实际上并不是例外情况,Error
来自LinkageError
而ClassNotFoundException
直接来自java.lang.Exception
。
要恢复,全局NoClassDefFoundError
只是表示JVM
尝试访问runtime
根据compiled
代码存在的内容,但实际上并不存在(或不在类路径中)。
重现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();
}
}
}
重现NoClassDefFoundError的示例
创建一个简单的类Test
public class Test {
public Test() {
System.out.println("A new instance of the Test class was created!");
}
}
班级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!");
}
}
现在创建一个执行.jar
方法的可执行文件main
。您可以在Manifest.txt
.jar
文件中指定它
Main-Class: NoClassDefFoundErrorExample
现在运行以下命令
javac Test.java
javac NoClassDefFoundErrorExample.java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
java -jar NoClassDefFoundErrorExample.jar
注意NoClassDefFoundError
Exception in thread "main" java.lang.NoClassDefFoundError: TestClass
at NoClassDefFoundErrorExample.(NoClassDefFoundErrorExample.java:2)
Caused by: java.lang.ClassNotFoundException: TestClass
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.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
答案 1 :(得分:10)
嗯... ClassNotFoundException
发生在运行时试图找到某个String
命名的类时,例如Class.forName(java.lang.String)
方法取一个字符串参数并尝试用这个来查找类名称。在这种情况下,类名是一个sting,只能在运行时检查。这里的例外清楚地说......没有找到这个“阶级”。所以......它可能有两个原因:
原因1.类名不是有效的java类(例如“java.bang.kiting”)。
// Example
Class cdef = Class.forName( "java.bang.kiting" );
原因2.类名是一个有效的类...但不知何故它没有与jar打包或在类路径中没有解析。因此,就运行时所知......它可能是一个错误的类名...类似于情况1。
// Example
Class cdef =Class.forName( "apache.some.SomeLegitClass" );
对于使用实际类引用的情况,NoClassDefFoundError
,
// example
import apache.some.SomeLegitClass
SomeLegitClass i = (SomeLegitClass) instanceOfSomeLegitClass;
所以基本上一切都是正确的,但不知何故,这个类没有与jar打包(或者更一般地说 - 在类路径中没有解决)。在这种情况下,我们得到NoClassDefFoundError
。
这里运行时知道该类是有效的,因为它已成功编译...但它找不到“类定义”。
答案 2 :(得分:2)
NoClassDefFoundError
。您将库放在项目的类路径中,但是您没有将它们一起导出,当应用程序运行时,您将获得NoClassDefFoundError
。
如何获得NoClassDefFoundError
:
使用此类创建一个新项目。
public class A
{
public void do()
{
System.out.println("Do!");
}
}
将其导出为.jar
文件。
现在创建另一个项目。将导出的jar文件添加到classpath。
import ???.A;
public class Main
{
public static void main(String[] args)
{
A a = new A();
a.do();//NoClassDefFoundError thrown at here.
}
}
导出项目,确保不包含jar文件(使用类A
)。运行新导出的jar文件,您将看到该错误!
答案 3 :(得分:1)
1) ClassNotFoundException
Class.forName()
或ClassLoader.loadClass()
或ClassLoader.findSystemClass()
方法在运行时加载一个类时,会发生这种情况,并且不可以找到所需的类路径中的类。 class path
并在类路径中添加该类(如果缺少)。2) NoClassDefFoundError
当compile time
期间出现该课程时出现这种情况,并且由于某些原因在run time
期间无法使用。这意味着加载的类在present
中为classpath
,但此类所需的其中一个依赖classe(s)
要么已删除,要么失败由编译器加载。
在这种情况下,我们只需要查看classes which are dependent on this class
。
答案 4 :(得分:1)
如前面的答案中所述,当编译时出现类时,NoClassDefFoundError会出现,并且由于某些原因在运行时不可用。
我想添加另一个场景,这也可能导致NoClassDefFoundError。
当您尝试加载由于某些异常导致无法加载的类时,表示静态初始化块失败,系统将抛出ExceptionInInitializerError。如果再次尝试加载同一个类(以前无法加载),系统将抛出NoClassDefFoundError
让我们用样本
来探索它<强> 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();
}
}
}
<强>结果:强>
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
让我们修改 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
}
}
<强>结果:强>
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)
当我们再次尝试使用ClassWithStaticBlock时(之前未能初始化),System正在抛出NoClassDefFoundError。
找到样本答案 5 :(得分:0)
在运行时未找到特定类时会发生ClassNotFoundException和NoClassDefFoundError。但是,它们出现在不同的场景中。
ClassNotFoundException是当您尝试使用Class.forName()或loadClass()方法在运行时加载类时发生的异常,并且在类路径中找不到提到的类。
public class MainClass
{
public static void main(String[] args)
{
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
}catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at pack1.MainClass.main(MainClass.java:17)
NoClassDefFoundError是在编译时出现特定类但在运行时丢失时发生的错误。
class A
{
// some code
}
public class B
{
public static void main(String[] args)
{
A a = new A();
}
}
编译上述程序时,将生成两个.class文件。一个是A.class,另一个是B.class。如果删除A.class文件并运行B.class文件,Java Runtime System将抛出NoClassDefFoundError,如下所示:
Exception in thread "main" java.lang.NoClassDefFoundError: A
at MainClass.main(MainClass.java:10)
Caused by: java.lang.ClassNotFoundException: A
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
答案 6 :(得分:0)
Everything About ClassNotFoundException Vs NoClassDefFoundError文章非常清楚地解释了ClassNotFoundException与NoClassDefFoundError之间的区别,并根据它进行了解释。
当我们告诉JVM使用Class.forName()或ClassLoader.findSystemClass()或ClassLoader.loadClass()方法通过其字符串名称加载类时发生的已检查异常,并且在类路径中找不到提到的类。
大多数情况下,当您尝试运行应用程序而不使用所需的JAR文件更新类路径时,会发生此异常。例如,在执行JDBC代码连接到数据库时,可能已经看到了这个异常,即MySQL,但是你的类路径没有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");
}
}
java.lang.Error的子类型和Error类表示应用程序实际上不应该发生的异常行为,但应用程序开发人员不应该尝试捕获它,它只适用于JVM。
当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");
}
}
答案 7 :(得分:-1)
这个帖子中的其他答案是正确的,我只想添加一些我花费数小时试图找出的东西。即使
Class.forName("apache.some.SomeLegitClass")
作品,
Class.forName("apache.some.somelegitclass")
将导致NoClassDefFoundError。 Class.forName()区分大小写。如果类名拼写错误,或者只是包含不正确的大小写,则会导致不同的异常。