Java lang noclassdeffounderror как исправить
Перейти к содержимому

Java lang noclassdeffounderror как исправить

  • автор:

Способы исправления java.lang.NoClassDefFoundError в Java J2EE

Переводчик выражает благодарность Виктору Жуковскому за ценные правки и обсуждение рукописи.

Введение

Известно насколько неприятно видеть исключение java.lang.NoClassDefFoundError в потоке » main «. Многие разработчики проводят много времени прежде всего пытаясь понять, что пошло не так, какого класса не хватает и в чём суть проблемы. Во-первых, они путают между собой ClassNotfoundException и NoClassDefFoundError , хотя на самом деле это два совершенно разных исключения. Во-вторых, они используют метод «научного тыка» для решения проблемы NoClassDefFoundError вместо ясного понимания почему ошибка случилась и как её исправить. В этой статье по Java мы откроем некоторые секреты исправления ошибки NoClassDefFoundError в Java и поделимся своим опытом решения подобной проблемы.

Ошибка NoClassDefFoundError не является чем-то, что не может быть устранено или чем-то, что очень трудно устраняемо — нет, NoClassDefFoundError всего лишь проявление другой, более глубинной ошибки, что сбивает с толку большинство Java разработчиков. NoClassDefFoundError наиболее распространённая ошибка в Java разработке наряду с java.lang.OutOfMemoroyError: Java heap space и java.lang.OutOfMemoryError: PermGen space . Давайте посмотрим почему в Java происходит NoClassDefFoundError и что делать, чтобы её исправить.

В чём причина NoClassDefFoundError в Java?

NoClassDefFoundError в Java происходит тогда, когда виртуальная машина Java во время исполнения кода не может найти определённый класс, который был доступен во время компиляции. Например, если мы вызываем метод из класса или обращаемся к статическому члену класса и этот класс не доступен во время выполнения, то виртуальная машина Java выбрасывает NoClassDefFoundError . Важно понимать, что эта ошибка отличается от исключения ClassNotFoundException , которое происходит при попытке загрузки класса во время выполнения, причём важно, что имя этого класса было определено только во время выполнения, но не во время компиляции кода. Многие Java разработчики путают эти две ошибки и приходят в тупик при попытке разрешить вопрос.

Коротко говоря, NoClassDefFoundError происходит, если класс присутствовал во время компиляции, но не доступен в classpath во время исполнения. Обычно в этом случае вы увидите следующую строку в журнале ошибок:

Exception in thread «main» java.lang.NoClassDefFoundError

Фраза Exception in thread «main» означает, что именно поток » main » не может найти определённый класс. Вместо » main » может быть любой поток. Разница между тем, когда эта ошибка возникает в потоке » main » и в другом потоке в состоит том, что при возникновении в потоке » main » программа останавливается, а при возникновении в ином потоке, напротив, продолжает выполнение после ошибки.

Разница между java.lang.NoClassDefFoundError и ClassNotFoundException в Java

Прежде чем рассмотреть разницу между ClassNotFoundException и NoClassDefFoundError давайте рассмотрим, что между ними общего и что приводит к путанице между этими двумя ошибками:

  • Обе ошибки связаны с недоступностью класса во время выполнения;
  • Обе ошибки связаны с Java Classpath .

Теперь о различиях.

  • ClassNotFoundException возникает в Java, если мы пытаемся загрузить класс во время выполнения используя методы Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() , причём необходимый класс не доступен для Java. Зачастую причина тому — неправильный Classpath . В большинстве своём нам кажется, что мы используем корректный Classpath , но оказывается, что приложение использует совсем другой Classpath — не тот, который мы ожидали. Например, Classpath , заданный в манифесте jar файла, перезаписывает Classpath в переменной окружения CLASSPATH или опции -cp , заданной при запуске jar файла. В отличие от ClassNotFoundException в случае с NoClassDefFoundError проблемный класс присутствовал во время компиляции, и, поэтому, программа успешно прошла компиляцию, но по некоторой причине класс отсутствует во время исполнения. На мой взгляд решить NoClassDefFoundError легче чем ClassNotFoundException , поскольку вы точно знаете, что класс присутствовал во время сборки, но, в общем случае, это сильно зависит от среды разработки. Если вы работаете с J2EE окружением, вы можете получить NoClassDefFoundError даже если класс присутствует, поскольку он может быть невидимым для соответствующего загрузчика классов.
  • ClassNotFoundException представляет собой проверяемое исключение, унаследованное непосредственно от класса java.lang.Exception , требующее явной обработки, в то время как NoClassDefFoundError это java.lang.Error , унаследованный от java.lang.LinkageError .
  • ClassNotFoundException возникает в результате явной загрузки класса методами Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() , в то время как NoClassDefFoundError — результат неявной загрузки класса, происходящей при попытке вызова метода из другого класса или доступа к его свойству.

NoClassDefFoundError в Java. Примеры и сценарии

Итак, очевидная причина NoClassDefFoundError состоит в том, что определённый класс не доступен в Classpath , так что нам нужно добавить его в Classpath или понять почему его нет в Classpath , хотя мы ожидаем его там найти. Для этого могут быть несколько причин:

  1. Класс не задан непосредственно в самой переменной Classpath .
    • Распечатайте значение System.getproperty(«java.classpath») в Java программе.
    • Проверьте, не перезаписывает ли значение переменной окружения Classpath скрипт, запускающий приложение. Запустите программу с явной опцией -classpath , где укажите тот classpath , который по вашему мнению сработает, и если в этом случае программа заработает, то это хороший знак, что кто-то перезатирает ваш classpath .
  2. Класс отсутствует по местоположению, указанному в переменной Classpath .
    • Проверьте, не удалил ли кто-то ваш jar-файл, или быть может переименовал его.
  3. Загрузчик классов не имеет прав на чтение файла, указанного в переменной Classpath , на уровне операционной системы.
    • Используйте один и тот же id пользователя для всех ресурсов вашего приложения: JAR файлов, библиотек и файлов конфигурации.
  4. Класс не определён в атрибуте ClassPath файла манифеста, при запуске программы с помощью команды jar .
    • Если вы используете файл сборки ANT для создания JAR архива и файла манифеста, то проверьте получает ли скрипт сборки ANT правильное значение classpath и добавляет ли его в файл manifest.mf .
  5. Виртуальная машина Java не нашла одну из зависимостей, например, нативную библиотеку. Эта ошибка выбрасывается поскольку NoClassDefFoundError является наследником java.lang.LinkageError .
    • Храните ваши dll совместно с jar-файлами.
  6. Виртуальная машина Java не смогла завершить статическую инициализацию класса.
    • Проверьте наличие ошибки java.lang.ExceptionInInitializerError в вашем журнале ошибок.
  7. Родительский загрузчик классов не видит класс, поскольку тот был уже загружен дочерним загрузчиком. Если вы работаете со средой J2EE, то неверная настройка видимости класса среди загрузчиков классов может также привести к java.lang.NoClassDefFoundError .
  8. Опечатка в XML конфигурации также может привести к NoClassDefFoundError в Java. Большинство программных платформ вроде Spring и Struts используют XML конфигурации для определения бинов. Случайно перепутав имя бина, вы можете получить java.lang.NoClassDefFoundError при загрузке другого класса, который зависит от бина. Это случается довольно часто в программных платформах Spring MVC и Apache Struts, где вы получаете тонны ошибок Exception in thread «main» java.lang.NoClassDefFoundError во время установки WAR или EAR файла.
  9. Переменные окружения или JDK установлены неверно.
    • Проверьте переменные PATH и JAVA_HOME .
    • Поставьте JDK другой версии.

Загрузчик классов в Java

Вкратце напомним, что загрузчик классов использует три основных принципа в своей работе: делегирование, видимость и уникальность.

  • Делегирование означает, что каждый запрос на загрузку класса делегируется родительскому загрузчику классов.
  • Видимость означает возможность найти классы загруженные загрузчиком классов: все дочерние загрузчики классов могут видеть классы, загруженные родительским загрузчиком, но родительский загрузчик не может видеть класс, загруженный дочерним.
  • Уникальность гарантирует, что класс, загруженный родительским загрузчиком, не загружается повторно дочерним загрузчиком.

Каждый экземпляр загрузчика классов имеет связанный с ним родительский загрузчик классов. Предположим, загрузчик классов вашего приложения должен загрузить класс A . Первым делом загрузчик классов вашего приложения попытается делегировать поиск класса A своему родительскому загрузчику, прежде чем сам попытается его загрузить. Вы можете пройтись по длинной цепочке родительских загрузчиков пока не дойдёте до стартового загрузчика виртуальной машины Java.

Так в чём же тут проблема? Если класс A найден и загружен каким-нибудь родительским загрузчиком, это значит, что дочерний загрузчик загружать его уже не будет, а вы, возможно, именно этого и ждёте, что и приводит к NoClassDefFoundError .

Для лучшего понимания изобразим весь процесс загрузки в контексте платформы Java EE.

Схема делегирования загрузки в контексте платформы Java EE

Как вы можете видеть при попытке загрузки класса дочерний загрузчик (Web App #1) делегирует загрузку родительскому загрузчику (Java EE App #1), который в свою очередь делегирует её системному стартовому загрузчику JVM. Если системный стартовый загрузчик не может загрузить класс, он возвращает управление родительскому загрузчику и так далее по цепочке пока класс не будет загружен каким-либо загрузчиком.

Рассмотрим простой пример, приводящий к NoClassDefFoundError из-за разной видимости классов между дочерним и родительским загрузчиками. Сделаем свой загрузчик MyClassLoader , наследник от java.lang.ClassLoader такой, чтобы он загружал классы с расширением .test вместо .class , находящиеся в пакете net.javacogito . Отметим, что стандартный загрузчик по умолчанию загружает данные только из файлов с расширением .class , так что загрузить Bar.test он не сможет. Схема дальнейшей работы такая:

  1. JVM загружает класс Bar из файла Bar.test .
  2. Класс Bar печатает свой загрузчик классов. Это MyClassLoader .
  3. JVM загружает класс Foo из файла Foo.class .
  4. Класс Foo печатает свой загрузчик классов. Это sun.misc.Launcher.AppClassLoader .
  5. Класс Foo вызывает статический метод printClassLoader() у класса Bar .

В этот момент JVM выдаёт NoClassDefFoundError , не смотря на то, что Bar был загружен ранее, поскольку родительский загрузчик AppClassLoader не видит классы, загруженные дочерним загрузчиком MyClassLoader .

Ниже на рисунке изображена схема делегирования загрузки, приводящая к NoClassDefFoundError .

Схема делегирования загрузки

Исходный код. Класс Bar .

package net.javacogito; public class Bar < public static void printClassLoader() < System.out.println("Bar ClassLoader: " + Bar.class.getClassLoader()); >>
package net.javacogito; public class Foo < public static void printBarClassLoader()< Bar.printClassLoader(); >public static void printClassLoader() < System.out.println("Foo ClassLoader: " + Foo.class.getClassLoader()); >>
package net.javacogito; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; public class MyClassLoader extends ClassLoader < public MyClassLoader(ClassLoader parent) < super(parent); >@Override public Class loadClass(String name) throws ClassNotFoundException < System.out.println("Loading Class '" + name + "'"); if (name.startsWith("net.javacogito")) < System.out.println("Loading Class using MyClassLoader"); return getClass(name); >return super.loadClass(name); > private Class getClass(String name) throws ClassNotFoundException < String file = name.replace('.', File.separatorChar) + ".test"; byte[] b = null; try < b = loadClassFileData(file); Class c = defineClass(name, b, 0, b.length); resolveClass(c); return c; >catch (IOException e) < e.printStackTrace(); return null; >> private byte[] loadClassFileData(String name) throws IOException < InputStream stream = getClass().getClassLoader().getResourceAsStream(name); int size = stream.available(); byte buff[] = new byte[size]; DataInputStream in = new DataInputStream(stream); in.readFully(buff); in.close(); return buff; >>
package net.javacogito; import java.lang.reflect.Method; public class Runner < public static void main(String[] args) throws Exception< MyClassLoader myClassLoader = new MyClassLoader(Runner.class.getClassLoader()); Class clazz = myClassLoader.loadClass("net.javacogito.Bar"); Method printClassLoader = clazz.getMethod("printClassLoader"); printClassLoader.invoke(null, new Object[0]); Foo.printClassLoader(); Foo.printBarClassLoader(); >>
cd src/main/java javac net/javacogito/Runner.java mv net/javacogito/Bar.class net/javacogito/Bar.test java net.javacogito.Runner
Loading Class 'net.javacogito.Bar' Loading Class using MyClassLoader Loading Class 'java.lang.Object' Loading Class 'java.lang.System' Loading Class 'java.lang.StringBuilder' Loading Class 'java.lang.Class' Loading Class 'java.io.PrintStream' Bar ClassLoader: net.javacogito.MyClassLoader@527c6768 Foo ClassLoader: sun.misc.Launcher$AppClassLoader@3326b249 Exception in thread "main" java.lang.NoClassDefFoundError: net/javacogito/Bar at net.javacogito.Foo.printBarClassLoader(Foo.java:5) at net.javacogito.Runner.main(Runner.java:16) Caused by: java.lang.ClassNotFoundException: net.javacogito.Bar at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) . 2 more

Из результатов запуска видно, что MyClassLoader загрузил класс Bar , а AppClassLoader (наследник абстрактного класса java.lang.ClassLoader ) загрузил класс Foo . Класс Bar присутствует в файловой системе и JVM его загрузила, но родительский загрузчик ClassLoader не видит его, что и приводит к NoClassDefFoundError .

NoClassDefFoundError в Java из-за исключения в статическом инициализирующем блоке

Исключения в статическом инициализирующем блоке — другая частая причина java.lang.NoClassDefFoundError . Ваш класс выполняет некоторую статическую инициализацию в статическом блоке. Например, многие синглетоны инициализируют себя в статическом блоке, чтобы получить преимущества потоко-безопасности, предоставляемые виртуальной машиной Java во время процесса инициализации класса. В этом случае, если статический блок выбросит исключение, то класс, ссылающийся на этот синглетон, выбросит NoclassDefFoundError в Java. При просмотре вашего журнала ошибок вы должны внимательно следить, не возникла ли ошибка java.lang.ExceptionInInitializerError , поскольку она может привести к java.lang.NoClassDefFoundError: Could not initialize class в другом месте. Как и в примере кода ниже, во время загрузки и инициализации класс User выбрасывает исключение из статического инициализирующего блока, что приводит к ExceptionInInitializerError во время первой загрузки класса User при вызове new User() . Дальше все остальные вызовы new User() завершаются java.lang.NoClassDefFoundError . Ситуация становится намного хуже, если исходную ошибку ExceptionInInitializerError , являющуюся первопричиной, скрывает последующий код.

/** * Java program to demonstrate how failure of static initialization subsequently cause * java.lang.NoClassDefFoundError in Java. * @author Javin Paul */ public class NoClassDefFoundErrorDueToStaticInitFailure < public static void main(String args[])< Listusers = new ArrayList(2); for(int i=0; icatch(Throwable t) < t.printStackTrace(); >> > > class User < private static String USER_ID = getUserId(); public User(String id)< this.USER_ID = id; >private static String getUserId() < throw new RuntimeException("UserId Not found"); >>
java.lang.ExceptionInInitializerError at testing.NoClassDefFoundErrorDueToStaticInitFailure.main(NoClassDef FoundErrorDueToStaticInitFailure.java:23) Caused by: java.lang.RuntimeException: UserId Not found at testing.User.getUserId(NoClassDefFoundErrorDueToStaticInitFailure.java:41) at testing.User.(NoClassDefFoundErrorDueToStaticInitFailure.java:35) . 1 more java.lang.NoClassDefFoundError: Could not initialize class testing.User at testing.NoClassDefFoundErrorDueToStaticInitFailure.main(NoClassDef FoundErrorDueToStaticInitFailure.java:23)

Перечень использованных ссылок

  1. http://javarevisited.blogspot.com/2011/07/classnotfoundexception-vs.html
  2. http://javarevisited.blogspot.com/2011/06/noclassdeffounderror-exception-in.html
  3. http://stackoverflow.com/questions/1457863/what-is-the-difference-between-noclassdeffounderror-and-classnotfoundexception
  4. http://www.javacodegeeks.com/2012/06/javalangnoclassdeffounderror-how-to.html
  • Страницы с ошибками в подсветке синтаксиса
  • Переводы на русский язык

Как исправить java.lang.ClassNotFoundException

Aspose.Cells for Java API зависит от некоторых дополнительных библиотек, если они отсутствуют, может быть выдано исключение “java.lang.ClassNotFoundException”. В этой статье перечислены такие исключения и объяснено, какие библиотеки установлены для их устранения.

Как исправить ClassNotFoundException: org.bouncycastle.jce.provider.BouncyCastleProvider

Краткое содержание

Aspose.Cells for Java API зависит от функций шифрования и дешифрования Bouncy Castle, то есть, если программе требуется загружать или сохранять зашифрованные электронные таблицы, необходимо добавить ссылку на bcprov-jdk16-146.jar в путь к классам проекта.

Симптомы

Вы можете получить исключение java.lang.ClassNotFoundException: org.bouncycastle.jce.provider.BouncyCastleProvider.

Решение

Решение на самом деле очень простое, как описано ниже.

  1. Загрузите любую крупную версиюAspose.Cells for Java.
  2. Распакуйте загруженный архив и перейдите в каталог \JDK 1.6\aspose-cells-xx0-java\lib.
  3. Создайте ссылку на bcprov-jdk16-146.jar в пути к классам проекта.

Альтернативно вы можете добавить зависимость в pom.xml и позволить проекту разрешить зависимость через maven.

 dependencies> dependency> groupId>org.bouncycastlegroupId> artifactId>bcprov-jdk16artifactId> version>1.46version> type>jartype> dependency> dependencies>

Как исправить ошибку: Exception in thread «main» java.lang.NoClassDefFoundError: com/github/sarxos/v4l4j/V4L4J?

sergueik

Было на Githab 5 лет назад 🙂
Само сообщение о том, что для выполнения java не может найти и подключить нужный класс, нужно добавить готовые jar в пути выполнения CLASSPATH или в сборку добавить как артефакт вручную.

Переписать файл JAR с недостающими классами в /lib .
Руками добавить себе в pom.xml файл в корне проекта:

 webcam-capture-driver-v4l4j webcam-capture-driver-v4l4j 0.3.11-SNAPSHOT system $/lib/yourJar.jar 

После добавления в pom.xml описание зависимости появится в IDE (допустим Netbeans), но не скачается, нажать «Установить зависимость вручную» и указать на локальный jar в lib каталоге.

Вот оригинальный коммент с Github (ссылка на Jar вроде уже нерабочая, вот он):
sarxos commented on 22 May 2015
@charlie23k,

Yes, it’s possible to use Webcam Capture API with RasPi Camera Module.

The NoClassDefFoundError clearly states that you are missing some classes. This is because you haven’t add required JARs into your application’s classpath.

On the page I linked in the previous post:

There is a statement:

The following JARs are required:

The webcam-capture-driver-v4l4j JAR can be found here, and
The V4L4J JAR itself which can be found here (the project and source code is available here).
Which means that you have to download them and add to your application’s classpath. Otherwise the code will not work and will rise exception same as yours. You are missing JAR from second bullet (V4L4J). It can be found here:

Как решить java.lang.ClassNotFoundException

Эта статья предназначена для начинающих Java, которые в настоящее время сталкиваются с проблемами java.lang.ClassNotFoundException. Он предоставит вам обзор этого распространенного исключения Java, пример Java-программы для поддержки вашего процесса обучения и стратегии решения.

Если вас интересуют более сложные проблемы, связанные с загрузчиком классов, я рекомендовал вам просмотреть мою серию статей на
java.lang.NoClassDefFoundError, так как эти исключения Java тесно связаны.

java.lang.ClassNotFoundException: обзор

Согласно документации Oracle,
ClassNotFoundException генерируется после сбоя вызова загрузки класса с использованием его строкового имени, как показано ниже:

  • Метод Class.forName
  • Метод ClassLoader.findSystemClass
  • Метод ClassLoader.loadClass

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

Эта проблема может быть особенно запутанной для начинающих Java. Вот почему я всегда рекомендую разработчикам Java изучать и совершенствовать свои знания о
загрузчиках классов Java . Если вы не вовлечены в динамическую загрузку классов и не используете Java Reflection API, есть вероятность, что ошибка ClassNotFoundException, которую вы получаете, связана не с кодом вашего приложения, а с API-интерфейсом, на который ссылаются. Другая распространенная проблема — неправильная упаковка кода вашего приложения. Мы вернемся к стратегии разрешения в конце статьи.

java.lang.ClassNotFoundException: пример Java-программы

Теперь найдите ниже очень простую Java-программу, которая имитирует 2 наиболее распространенных сценария ClassNotFoundException с помощью Class.forName () и ClassLoader.loadClass (). Пожалуйста, просто скопируйте / вставьте и запустите программу с IDE по вашему выбору (
Eclipse IDE был использован для этого примера ).

Программа Java позволяет вам выбирать между проблемным сценарием № 1 или проблемным сценарием № 2, как показано ниже. Просто измените на 1 или 2 в зависимости от сценария, который вы хотите изучить.

# Class.forName() private static final int PROBLEM_SCENARIO = 1; # ClassLoader.loadClass() private static final int PROBLEM_SCENARIO = 2;

# ClassNotFoundExceptionSimulator

package org.ph.javaee.training5; /** * ClassNotFoundExceptionSimulator * @author Pierre-Hugues Charbonneau * */ public class ClassNotFoundExceptionSimulator < private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassA"; private static final int PROBLEM_SCENARIO = 1; /** * @param args */ public static void main(String[] args) < System.out.println("java.lang.ClassNotFoundException Simulator - Training 5"); System.out.println("Author: Pierre-Hugues Charbonneau"); System.out.println("http://javaeesupportpatterns.blogspot.com"); switch(PROBLEM_SCENARIO) < // Scenario #1 - Class.forName() case 1: System.out.println("\n** Problem scenario #1: Class.forName() **\n"); try < ClassnewClass = Class.forName(CLASS_TO_LOAD); System.out.println("Class "+newClass+" found successfully!"); > catch (ClassNotFoundException ex) < ex.printStackTrace(); System.out.println("Class "+CLASS_TO_LOAD+" not found!"); >catch (Throwable any) < System.out.println("Unexpected error! "+any); >break; // Scenario #2 - ClassLoader.loadClass() case 2: System.out.println("\n** Problem scenario #2: ClassLoader.loadClass() **\n"); try < ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ClasscallerClass = classLoader.loadClass(CLASS_TO_LOAD); Object newClassAInstance = callerClass.newInstance(); System.out.println("SUCCESS!: "+newClassAInstance); > catch (ClassNotFoundException ex) < ex.printStackTrace(); System.out.println("Class "+CLASS_TO_LOAD+" not found!"); >catch (Throwable any) < System.out.println("Unexpected error! "+any); >break; > System.out.println("\nSimulator done!"); > >

# ClassA

package org.ph.javaee.training5; /** * ClassA * @author Pierre-Hugues Charbonneau * */ public class ClassA < private final static ClassCLAZZ = ClassA.class; static < System.out.println("Class loading of "+CLAZZ+" from ClassLoader '"+CLAZZ.getClassLoader()+"' in progress. "); >public ClassA() < System.out.println("Creating a new instance of "+ClassA.class.getName()+". "); doSomething(); >private void doSomething() < // Nothing to do. >>

Если вы запустите программу как есть, вы увидите вывод, как показано ниже для каждого сценария:

Вывод сценария 1 (базовый уровень)

java.lang.ClassNotFoundException Simulator - Training 5 Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.com ** Problem scenario #1: Class.forName() ** Class loading of class org.ph.javaee.training5.ClassA from ClassLoader 'sun.misc.Launcher$AppClassLoader@bfbdb0' in progress. Class class org.ph.javaee.training5.ClassA found successfully! Simulator done!

Вывод сценария 2 (базовый уровень)

java.lang.ClassNotFoundException Simulator - Training 5 Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.com ** Problem scenario #2: ClassLoader.loadClass() ** Class loading of class org.ph.javaee.training5.ClassA from ClassLoader 'sun.misc.Launcher$AppClassLoader@2a340e' in progress. Creating a new instance of org.ph.javaee.training5.ClassA. SUCCESS!: org.ph.javaee.training5.ClassA@6eb38a Simulator done!

Для «базового» запуска Java-программа может успешно загрузить ClassA.

Теперь давайте добровольно изменим полное имя ClassA и повторно запустим программу для каждого сценария. Может быть получен следующий вывод:

#ClassA изменен на
ClassB

private static final String CLASS_TO_LOAD = "org.ph.javaee.training5.ClassB";

# Вывод сценария 1 (проблема репликации)

java.lang.ClassNotFoundException Simulator - Training 5 Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.com ** Problem scenario #1: Class.forName() ** java.lang.ClassNotFoundException: org.ph.javaee.training5.ClassB at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main(ClassNotFoundExceptionSimulator.java:29) Class org.ph.javaee.training5.ClassB not found! Simulator done!

Вывод сценария 2 (проблема репликации)

java.lang.ClassNotFoundException Simulator - Training 5 Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.com ** Problem scenario #2: ClassLoader.loadClass() ** java.lang.ClassNotFoundException: org.ph.javaee.training5.ClassB at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) at org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main(ClassNotFoundExceptionSimulator.java:51) Class org.ph.javaee.training5.ClassB not found! Simulator done!

Что произошло? Итак, поскольку мы изменили полное имя класса на org.ph.javaee.training5.ClassB, такой класс не был найден во время выполнения (не существует), что привело к сбою вызовов Class.forName () и ClassLoader.loadClass ().

Вы также можете повторить эту проблему, упаковав каждый класс этой программы в свой собственный JAR-файл, а затем пропустите jar-файл, содержащий ClassA.class, из основного пути к классу. Попробуйте это и посмотрите сами результаты… (подсказка: NoClassDefFoundError)

Теперь давайте перейдем к стратегии разрешения.
java.lang.ClassNotFoundException: стратегии разрешения

Теперь, когда вы понимаете эту проблему, пришло время решить ее. Разрешение может быть довольно простым или очень сложным в зависимости от первопричины.

  • Не спешите со сложными первопричинами слишком быстро, сначала исключите самые простые причины.
  • Сначала просмотрите трассировку стека java.lang.ClassNotFoundException согласно приведенному выше и определите, какой класс Java не был загружен должным образом во время выполнения, например, код приложения, сторонний API, сам контейнер Java EE и т. Д.
  • Определите вызывающего, например, Java-класс, который вы видите по трассировке стека непосредственно перед вызовами Class.forName () или ClassLoader.loadClass (). Это поможет вам понять, является ли код вашего приложения ошибочным по сравнению с API стороннего производителя.
  • Определите, правильно ли упакован код вашего приложения, например, отсутствуют файлы JAR из вашего classpath
  • Если отсутствующий класс Java отсутствует в коде вашего приложения, то определите, принадлежит ли он стороннему API, который вы используете в соответствии с вашим приложением Java. Как только вы определите его, вам нужно будет добавить отсутствующие JAR-файлы в ваш путь к классам во время выполнения или файл WAR / EAR веб-приложения.
  • Если после нескольких попыток разрешения проблемы все еще не решены, это может означать более сложную проблему иерархии загрузчиков классов. В этом случае, пожалуйста, просмотрите мою серию статей NoClassDefFoundError для большего количества примеров и стратегий разрешения

Я надеюсь, что эта статья помогла вам понять и вернуться к этому распространенному исключению Java.

Пожалуйста, не стесняйтесь оставлять комментарии или вопросы, если вы все еще боретесь с проблемой java.lang.ClassNotFoundException.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *