Каковы причины и в чем различия между NoClassDefFoundError и ClassNotFoundException? - PullRequest
359 голосов
/ 22 сентября 2009

В чем разница между NoClassDefFoundError и ClassNotFoundException?

Что заставляет их бросать? Как они могут быть решены?

Я часто сталкиваюсь с этими throwables при изменении существующего кода, чтобы включить новые файлы JAR. Я ударил их как на стороне клиента, так и на стороне сервера для Java-приложения, распространяемого через веб-запуск.

Возможные причины, с которыми я столкнулся:

  1. пакеты, не включенные в build.xml для клиентской части кода
  2. путь к классу выполнения отсутствует для новых jar-файлов, которые мы используем
  3. версия конфликтует с предыдущим jar

Когда я сталкиваюсь с этим сегодня, я использую метод «след и ошибка», чтобы все заработало. Мне нужно больше ясности и понимания.

Ответы [ 15 ]

3 голосов
/ 20 января 2015

Учитывая действия sussystem загрузчика класса:

http://www.artima.com/insidejvm/ed2/images/fig7-1.gif

Эта статья очень помогла мне понять разницу: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

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

Если виртуальная машина Java когда-либо пытается загрузить класс C во время проверка (§5.4.1) или разрешение (§5.4.3) (но не инициализация (§5.5)) и загрузчик классов, который используется для запуска загрузки C бросает экземпляр ClassNotFoundException , затем виртуальный Java Машина должна выбросить экземпляр NoClassDefFoundError , причина которого экземпляр ClassNotFoundException .

Итак, ClassNotFoundException является основной причиной NoClassDefFoundError .
И NoClassDefFoundError является частным случаем ошибки загрузки типа, которая возникает на шаге Linking .

2 голосов
/ 17 февраля 2012

Добавьте одну возможную причину на практике:

  • ClassNotFoundException: как сказал Клетус, вы используете интерфейс, в то время как унаследованный класс интерфейса не находится в пути к классам. Например, шаблон поставщика услуг (или указатель службы ) пытается найти какой-то несуществующий класс
  • NoClassDefFoundError: данный класс найден, а зависимость данного класса не найдена

На практике Ошибка может быть выброшено молча , например, вы отправляете задание таймера, а в задании таймера оно выбрасывает Ошибка , в то время как в большинстве случаев ваша программа перехватывает только Исключение . Затем основной цикл Timer завершается без какой-либо информации. Ошибка, аналогичная NoClassDefFoundError, равна ExceptionInInitializerError , когда ваш статический инициализатор или инициализатор статической переменной генерирует исключение.

1 голос
/ 08 апреля 2017

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

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

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

Ниже приведено краткое описание

enter image description here

Вы можете прочитать Все о ClassNotFoundException против NoClassDefFoundError для более подробной информации.

1 голос
/ 19 января 2017

Я снова и снова напоминаю себе следующее, когда мне нужно обновить

ClassNotFoundException

Иерархия классов

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

при отладке

  1. Необходимая банка, класс отсутствует в пути к классам.
  2. Убедитесь, что все необходимые банки находятся в classpath jvm.

NoClassDefFoundError

Иерархия классов

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

При отладке

  1. Проблема с динамической загрузкой класса, который был правильно скомпилирован
  2. Проблема со статическими блоками, конструкторами, методами init () зависимого класса и фактической ошибкой оборачивается несколькими слоями [особенно когда вы используете spring, hibernate оборачивается фактическим исключением, и вы получаете NoClassDefError]
  3. Когда вы сталкиваетесь с «ClassNotFoundException» в статическом блоке зависимого класса
  4. Проблема с версиями класса. Это происходит, когда у вас есть две версии v1, v2 одного и того же класса в разных jar / пакетах, которые были успешно скомпилированы с использованием v1, а v2 загружается во время выполнения, в котором нет соответствующих методов / vars, и вы увидите это исключение. [Однажды я решил эту проблему, удалив дубликат связанного с log4j класса под несколькими банками, которые появились в classpath]
0 голосов
/ 18 августа 2017

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)
...