Снова java.lang.NoClassDefFoundError
Здравствуйте. Я конечно понимаю,что для большинства вопрос будет простейший. И то что аналогичные вопросы задаются раз в неделю,но я новичок и помощи
Предисловие. При написание простой программы для вычисления факториала, после компиляции при запуске вылетает не без известная ошибка. Прочитал на —» Что это означает? А означает это вот что. Виртуальная машина нашла класс, который я пытаюсь запустить – Test. Нашла она его исключительно потому, что я сказал – искать в этой директории класс по имени Test. Прошу обратить внимание – по ПОЛНОМУ имени Test. Машина нашла его. Но класс-то на самом деле – test.Test. Именно об этом она и сообщает – wrong name: test/Test»
Внимание.И так вопрос от новичка, как это исправить?
Как делаю:
1)NetBeansProjects\Fact\src\fact>javac
2)NetBeansProjects\Fact\src\fact>java -classpath . Fact
и получаю..
Exception in thread «main» java.lang.NoClassDefFoundError: fact (wrong name: Fact/Fact)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:792)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
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:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
Ошибка java.lang.NoClassDefFoundError в JUnit
В этой статье мы поймем, почему в JUnit возникает ошибка java.lang.NoClassDefFoundError и как ее исправить. Эта проблема в основном связана с конфигурациями IDE. Поэтому мы сосредоточимся на самых популярных IDE: Visual Studio Code, Eclipse и IntelliJ, чтобы воспроизвести и устранить эту ошибку.
2. Что такое java.lang.NoClassDefFoundError ?
Когда среда выполнения Java запускает программу Java, она не загружает сразу все классы и зависимости. Вместо этого он вызывает загрузчик классов Java для загрузки классов в память по мере необходимости. При загрузке класса, если загрузчик классов не может найти определение класса, он выдает ошибку NoClassDefFoundError .
Есть несколько причин, по которым Java не может найти определение класса:
- Отсутствие нескольких зависимых банок, что является наиболее распространенной причиной.
- Все банки добавляются как зависимости, но по неправильному пути.
- Несоответствие версий в зависимостях .
3. Код ВС
Для написания тестовых случаев Junit4 нам требуется jar Junit4. Однако Junit4 имеет внутреннюю зависимость от jar ядра hamcrest .
Если мы пропустим добавление jar hamcrest-core в качестве зависимости в наш путь к классам, Java выдаст ошибку NoClassDefFoundError . Путь к классам выглядит следующим образом:
Еще один сценарий: мы добавили обе банки, но версии не совпадают. Например, если мы добавили JUnit jar версии 4.13.2 и jar версии 2.2 hamcrest-core , выдается NoClassDefFoundError :
В обоих случаях выводится одна и та же трассировка стека:
java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:855) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:753) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:676)
Чтобы устранить ошибку в обоих сценариях (отсутствующие зависимости и несоответствие версий), нам нужно добавить правильные зависимости. В случае с Junit4 правильными зависимостями являются junit-4.13.2.jar и hamcrest-core-1.3.jar . Добавление этих двух банок в зависимости (ссылочные библиотеки) устраняет ошибку. Инструкции по добавлению и удалению внешних jar-файлов в VS Code присутствуют здесь . Раздел библиотеки, на который мы ссылаемся, должен быть настроен как:
4. Затмение
В среде Eclipse IDE, которая поддерживает Java 9 и выше, у нас есть путь к классам и путь к модулю. Чтобы разрешить зависимость модуля, мы используем путь к модулю. Однако добавление внешних jar-файлов в путь к модулю не делает их доступными для загрузчика классов . Следовательно, загрузчик классов считает их отсутствующими зависимостями и выдает ошибку NoClassDefFoundError .
Следовательно, если наша зависимость выглядит так, как показано на изображении ниже, выполнение тестового примера Junit приводит к NoClassDefFoundError:
Трассировка стека, сгенерированная при выполнении теста JUnit, выглядит следующим образом:
java.lang.NoClassDefFoundError: org/junit/runner/manipulation/Filter at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:377) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.loadTestLoaderClass(RemoteTestRunner.java:381)
В Eclipse нам нужно добавить jar-файлы в путь к классам, а не в путь к модулю. Итак, чтобы правильно добавить внешние банки, следуйте по пути:
щелкните правой кнопкой мыши проект — > Путь сборки — > Настроить путь сборки
В открывшемся окне удалите банки из-под пути к модулю и добавьте их в путь к классам. Это устраняет NoClassDefFoundError . Правильный путь к классам для запуска JUnit должен быть похож на:
5. Интеллидж
Для запуска тестовых случаев JUnit 5 требуется как механизм Jupiter, так и API Jupiter. Механизм Jupiter внутренне зависит от API Jupiter, поэтому в большинстве случаев достаточно добавить только зависимость механизма Jupiter в pom.xml. Однако добавление только зависимости API Jupiter в наш pom.xml и отсутствие зависимости механизма Jupiter приводит к NoClassDefFoundError .
Неправильная настройка в pom.xml будет выглядеть так:
dependencies> dependency> groupId>org.junit.jupitergroupId> artifactId>junit-jupiter-apiartifactId> version>5.8.1version> scope>testscope> dependency> dependencies>
Запуск простого тестового примера с этой настройкой приводит к следующей трассировке стека:
Exception in thread "main" java.lang.NoClassDefFoundError: org/junit/platform/engine/TestDescriptor at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:375) at com.intellij.rt.junit.JUnitStarter.getAgentClass(JUnitStarter.java:230) .
В IntelliJ для исправления зависимостей нам нужно исправить pom.xml . Исправленный pom.xml выглядит так:
dependencies> dependency> groupId>org.junit.jupitergroupId> artifactId>junit-jupiter-apiartifactId> version>5.8.1version> scope>testscope> dependency> dependency> groupId>org.junit.jupitergroupId> artifactId>junit-jupiter-engineartifactId> version>5.8.1version> scope>testscope> dependency> dependencies>
В качестве альтернативы мы можем добавить junit-jupiter-engine, поскольку его добавление автоматически добавляет jar junit-jupiter-api в путь к классам и устраняет ошибку.
6. Резюме
В этой статье мы рассмотрели различные причины возникновения ошибки java.lang.NoClassDefFoundError в JUnit. Мы также видели, как мы устраняем ошибку в разных IDE. Весь код этого руководства доступен на GitHub .
Java – How to Fix java.lang.NoClassDefFoundError?
This article represents tips on How to Fix java.lang.NoClassDefFoundError when compiling a particular Java file. Please feel free to comment/suggest if I missed to mention one or more important points. Also, sorry for the typos.
- How to reproduce java.lang.NoClassDefFoundError?
- Why does the java.lang.NoClassDefFoundError occur in the first place?
- How to Fix the Error?
How to reproduce java.lang.NoClassDefFoundError?
Take a look at following Class file.
package com.test; public class HelloWorld < public static void main(String[] args) < System.out.println("Hello World! How are you?"); >>
Following are steps to reproduce the java.lang.NoClassDefFoundError.
- Save the above file as HelloWorld.java within any folder.
- Compile the file using javac command using following: “javac HelloWorld.java”
- Start the JVM using command such as “java HelloWorld”.
- Following error would show up:
java.lang.NoClassDefFoundError: HelloWorld (wrong name: com/test/HelloWorld) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(Unknown Source) at java.security.SecureClassLoader.defineClass(Unknown Source) at java.net.URLClassLoader.defineClass(Unknown Source) at java.net.URLClassLoader.access$100(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) 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 sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Why does the java.lang.NoClassDefFoundError occur in the first place?
Following happens when you start JVM using “java HelloWorld.java”:
- JVM tries to find “HelloWorld” class file within the cache. If found, the class loading is done which is then followed by linking, initialization and method execution.
- If the class is not found in the cache, JVM follows the delegation model to find the class. In this model, the “AppClassLoader” delegates the parent classloader (Extension classloader) to find the class (in ext directory) which then delegates the activity to BootClassLoader to find the class in %JAVA_HOME%/hre/lib/rt.jar.
- If not found, the AppClassLoader tries to find the class in current folder. However, given the package information, “com.test”, the class is expected to find in “com\test” folder.
How to fix the java.lang.NoClassDefFoundError?
Take a look at following Class file.
package com.test; public class HelloWorld < public static void main(String[] args) < System.out.println("Hello World! How are you?"); >>
Do following to print “Hello World! How are you?”:
- Create folder com/test
- Place the following file, HelloWorld.java in com/test folder.
- Compile the file from top most folder consisting of com folder using following command: “javac com\test\HelloWorld.java”
- From topmost folder consisting of com folder, execute the following command, “java com.test.HelloWorld”. And, it should be fine.
Ajitesh Kumar
I have been recently working in the area of Data analytics including Data Science and Machine Learning / Deep Learning. I am also passionate about different technologies including programming languages such as Java/JEE, Javascript, Python, R, Julia, etc, and technologies such as Blockchain, mobile computing, cloud-native technologies, application security, cloud computing platforms, big data, etc. For latest updates and blogs, follow us on Twitter. I would love to connect with you on Linkedin. Check out my latest book titled as First Principles Thinking: Building winning products using first principles thinking