Статьи

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

1
private static final int PROBLEM_SCENARIO = 1;

# ClassLoader.loadClass ()

1
private static final int PROBLEM_SCENARIO = 2;

# ClassNotFoundExceptionSimulator

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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 {
                                 Class<?> newClass = 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();           
                                 Class<?> callerClass = 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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.ph.javaee.training5;
 
/**
 * ClassA
 * @author Pierre-Hugues Charbonneau
 *
 */
public class ClassA {
 
private final static Class<ClassA> CLAZZ = 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
Симулятор — Тренировка 5

Автор: Пьер-Хьюг Шарбонно

http://javaeesupportpatterns.blogspot.com

** Проблемный сценарий № 1: Class.forName () **

Идет загрузка класса класса org.ph.javaee.training5.ClassA из ClassLoader ‘sun.misc.Launcher$AppClassLoader@bfbdb0’…

Класс класса org.ph.javaee.training5.ClassA найден успешно!

Симулятор готов!

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

java.lang.ClassNotFoundException
Симулятор — Тренировка 5

Автор: Пьер-Хьюг Шарбонно

http://javaeesupportpatterns.blogspot.com

** Проблемный сценарий № 2: ClassLoader.loadClass () **

Идет загрузка класса org.ph.javaee.training5.ClassA из ClassLoader ‘sun.misc.Launcher$AppClassLoader@2a340e’…

Создание нового экземпляра org.ph.javaee.training5.ClassA…

УСПЕХ !: org.ph.javaee.training5.ClassA@6eb38a

Симулятор готов!

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

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

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

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

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

java.lang.ClassNotFoundException
Симулятор — Тренировка 5

Автор: Пьер-Хьюг Шарбонно

http://javaeesupportpatterns.blogspot.com

** Проблемный сценарий № 1: Class.forName () **

java.lang.ClassNotFoundException
: org.ph.javaee.training5.ClassB

на java.net.URLClassLoader $ 1.run (
URLClassLoader.java:366
)

на java.net.URLClassLoader $ 1.run (
URLClassLoader.java:355
)

в java.security.AccessController.doPrivileged (
Родной метод
)

на java.net.URLClassLoader.findClass (
URLClassLoader.java:354
)

в java.lang.ClassLoader.loadClass (
ClassLoader.java:423
)

at sun.misc.Launcher $ AppClassLoader.loadClass (
Launcher.java:308
)

в java.lang.ClassLoader.loadClass (
ClassLoader.java:356
)

на java.lang.Class.forName0 (
Родной метод
)

на java.lang.Class.forName (
Class.java:186
)

в org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main (
ClassNotFoundExceptionSimulator.java:29
)

Класс org.ph.javaee.training5.ClassB не найден!

Симулятор готов!

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

java.lang.ClassNotFoundException
Симулятор — Тренировка 5

Автор: Пьер-Хьюг Шарбонно

http://javaeesupportpatterns.blogspot.com

** Проблемный сценарий № 2: ClassLoader.loadClass () **

java.lang.ClassNotFoundException
: org.ph.javaee.training5.ClassB

на java.net.URLClassLoader $ 1.run (
URLClassLoader.java:366
)

на java.net.URLClassLoader $ 1.run (
URLClassLoader.java:355
)

в java.security.AccessController.doPrivileged (
Родной метод
)

на java.net.URLClassLoader.findClass (
URLClassLoader.java:354
)

в java.lang.ClassLoader.loadClass (
ClassLoader.java:423
)

at sun.misc.Launcher $ AppClassLoader.loadClass (
Launcher.java:308
)

в java.lang.ClassLoader.loadClass (
ClassLoader.java:356
)

в org.ph.javaee.training5.ClassNotFoundExceptionSimulator.main (
ClassNotFoundExceptionSimulator.java:51
)

Класс org.ph.javaee.training5.ClassB не найден!

Симулятор готов!

Что произошло? Итак, поскольку мы изменили полное имя класса на 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.

Ссылка: java.lang.ClassNotFoundException: как решить проблему от нашего партнера по JCG Пьера-Хьюга Шарбонно из блога по шаблонам поддержки Java EE и учебному пособию по Java .