КлассNotFoundException vs NoClassDefFoundError - программирование

КлассNotFoundException vs NoClassDefFoundError

Я прошел через эту тему Какие причины и каковы различия между NoClassDefFoundError и ClassNotFoundException? Это то, что один из ans, который имеет max ups, в потоке: NoClassDefFoundError: "Итак, кажется, что NoClassDefFoundError возникает, когда источник был успешно скомпилирован, но во время выполнения необходимые файлы классов не были найдены. Это может быть что-то, что может происходят при распространении или выпуске JAR файлов, в которые были включены не все необходимые файлы классов.

ClassNotFoundException. Что касается ClassNotFoundException, похоже, что это может быть связано с попыткой сделать рефлексивные вызовы класса во время выполнения, но классы, которые программа пытается вызвать, не существует.

Я сделал небольшой эксперимент. Я создал основной класс класс A и попытался вызвать из него другой класс, класс B, скомпилированный успешно.

Затем я удалил класс B, который вызывается в классе A. Я получил 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 {



}
4b9b3361

Ответ 1

NoClassDefFoundError

Брошено, если экземпляр виртуальной машины Java или экземпляр ClassLoader пытается загрузить в определение класса (как часть обычного вызова метода или как часть создания нового экземпляра с использованием нового выражения), и нет определение класса можно найти.

Искаженное определение класса существовало, когда выполняемый в настоящее время класс был скомпилирован, но определение больше не может быть найдено.


ClassNotFoundException

Брошено, когда приложение пытается загрузить в класс через свою строку name using: метод forName в классе Class. FindSystemClass метод в классе ClassLoader. Метод loadClass в классе ClassLoader.


Вы должны понимать, что 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!");
        }
}

Теперь создайте n исполняемый .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

Ответ 2

Ну... ClassNotFoundException возникает, когда среда выполнения пытается найти класс с именем some String, например, метод Class.forName(java.lang.String) принимает строковый аргумент и пытается найти класс с этим именем. В этом случае имя класса является жалом и может быть проверено только во время выполнения. здесь исключение явно говорит... этот "класс" не найден. Итак... это может произойти по двум причинам:

Причина 1. Имя класса не является допустимым java-классом (пример - "java.bang.kiting" ).

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

Причина 2. Имя класса является допустимым классом... но каким-то образом он не был упакован с банкой или не разрешен в классе-пути. Так что, насколько известно время выполнения, это может быть неправильное имя класса... похожее на случай 1.

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

Где в качестве NoClassDefFoundError для случаев, когда использовалась фактическая ссылка класса,

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

Итак, в принципе все было правильно, но каким-то образом класс не упакован с банкой (или, более общо, не разрешен в классе-пути). В этом случае получим NoClassDefFoundError.

Здесь среда выполнения знает, что класс действителен, поскольку он скомпилирован успешно... но он не может найти "определение класса".

Ответ 3

Разница зависит от того, кто попросил загрузить класс:

  • ClassNotFoundException вызывается, когда код непосредственно пытается загрузить класс, передавая аргумент String, представляющий полностью квалифицированное имя класса.
    • например. Class.forName(String) или ClassLoader.loadClass(String).
  • NoClassDefFoundError вызывается, когда JVM предлагается загрузить класс косвенно.
    • например. когда класс A использует класс B, а класс B не находится в пути к классам, NoClassDefFoundError будет выбрано.

Ответ 4

NoClassDefFoundError обычно вызывается, когда вы используете библиотеку (например, Guava, Gson, CommonsIO). Вы помещаете библиотеку в classpath вашего проекта, но вы не экспортировали ее вместе, вы получите NoClassDefFoundError, когда приложение будет запущено.

Как получить NoClassDefFoundError:
Создайте новый проект с этим классом.

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

Экспортировать его как файл .jar.

Теперь создайте другой проект. Добавьте экспортированный файл jar в путь к классам.

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

Экспортируйте проект, убедитесь, что вы не включаете файл jar (с классом A). Запустите вновь экспортированный файл jar, вы увидите эту ошибку!

Ответ 5

1) КлассNotFoundException

  • Это происходит, когда мы пытаемся загрузить класс во время выполнения с помощью методов Class.forName() или ClassLoader.loadClass() или ClassLoader.findSystemClass(), и он мог не найти нужный класс в путь класса.
  • В этом случае мы должны проверить class path и добавить класс в путь класса, если он отсутствует.
  • Это checked Exception, который получен из класса java.lang.Exception.
  • Это происходит при загрузке явной.

2) NoClassDefFoundError

  • Это происходит, когда класс присутствовал во время compile time и недоступен во время run time по некоторым причинам. Это означает, что класс, который загружается, present в classpath, но один из зависимых classe(s), которые требуются этому классу, либо удален, либо не удалось для загрузки компилятором.

  • В этом случае нам нужно только проверить classes which are dependent on this class.

  • Это Ошибка, которая получена из java.lang.LinkageError.
  • Это происходит под неявной загрузкой.

Ответ 6

Как упоминалось в предыдущих ответах, 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 (который не был инициализирован ранее), система бросает NoClassDefFoundError.

Нашел образец из Почему я получаю NoClassDefFoundError в Java?

Ответ 7

Один из случаев, когда NoClassDefFoundError возникает, когда JVM класса пытается получить доступ, не найден в пути к классам. Но если класс присутствует в пути к классам, это приведет к ClassNotFoundException.

Короче, NoClassDefFoundError появится, если класс присутствовал во время компиляции, но не доступен в java classpath во время выполнения.

Просто попробуйте запустить с явным параметром -classpath, где classpath не содержит класс B.

Ответ 8

Другие ответы в этом потоке верны, я просто хочу добавить что-то, что я потратил часы, пытаясь понять. Даже если

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

работы

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

приведет к NoClassDefFoundError. Класс .forName() чувствителен к регистру. Это приведет к разным исключениям, если имя класса указано неправильно или просто имеет неправильную оболочку.

Ответ 9

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)

Ответ 10

Все о ClassNotFoundException Vs NoClassDefFoundError в статье объясняет разницу между ClassNotFoundException Vs NoClassDefFoundError очень четко с примером и в соответствии с ним.

ClassNotFoundException Vs NoClassDefFoundError - Программирование Mitra

ClassNotFoundException

Является проверенным исключением, которое возникает, когда мы указываем JVM на загрузку класса по его имени строки с использованием методов Class.forName() или ClassLoader.findSystemClass() или ClassLoader.loadClass(), и упомянутый класс не найден в пути к классам.

В большинстве случаев это исключение возникает при попытке запустить приложение без обновления пути к классам с требуемыми файлами JAR. Например, возможно, вы видели это исключение, когда код JDBC подключается к вашей базе данных i.e.MySQL, но ваш путь к классу не содержит банку.

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

Подтип класса java.lang.Error и Error указывает на ненормальное поведение, которое на самом деле не должно происходить с приложением, но разработчики приложений не должны пытаться его поймать, это только для использования JVM.

NoClassDefFoundError возникает, когда JVM пытается загрузить определенный класс, который является частью вашего исполнения кода (как часть обычного вызова метода или как часть создания экземпляра с использованием нового ключевого слова), и этот класс отсутствует в вашем пути к классам но присутствовал во время компиляции, потому что для выполнения вашей программы вам нужно скомпилировать ее, и если вы пытаетесь использовать класс, который отсутствует, компилятор вызовет ошибку компиляции.

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");
    }
}