Перейти к содержимому

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

  • автор:

Introduction

Amar Gurung

One of the common Error we encounter in Java applications is java.lang.NoClassDefFoundError

As per Oracle Java 8 Doc https://docs.oracle.com/javase/8/docs/api/java/lang/NoClassDefFoundError.html

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.

Why & How the issue may pop up

Our Application supports both Hadoop-2 & Hadoop-3 dependencies. Due to the major refactoring task of migrating the logging framework from log4j2 2.8 to Logback 1.2.3. We removed all the log4j2 dependencies from the code, and in the process, we forgot to test the application in the Hadoop-2 build.

The org.apache.hadoop.mapred.JobConf.class in the Hadoop-2 hadoop-mapreduce-client-core-2.7.2.jar still uses log4j imports. So, the Application code failed to initialize the Local FileSystem using Hadoop-2 dependent jars.

Java Code ( trimmed for clarity )

Exception Stack Trace

Analysis of JobConf.class

Source code for org.apache.hadoop.mapred.JobConf.class ( trimmed for clarity ) from hadoop-mapreduce-client-core-2.7.2.jar

Interestingly, the same piece of Java code is working fine with Hadoop-3. The reason being log4j imports are replaced with slf4j imports.

Source code org.apache.hadoop.mapred.JobConf.class ( trimmed for clarity ) from hadoop-mapreduce-client-core-3.2.0.jar

Identify & validate log4j-1.2-api-2.8.jar

Check whether org/apache/log4j/Level.class is present in log4j-1.2-api-2.8.jar using jar command.

Resolution:

After adding the log4j-1.2-api dependency in the application code. The issue got resolved.

java.lang.NoClassDefFoundError

java.lang.NoClassDefFoundError

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

java.lang.NoClassDefFoundError is runtime error thrown when a required class is not found in the classpath and hence JVM is unable to load it into memory.

java.lang.NoClassDefFoundError

java.lang.NoClassDefFoundError

  • NoClassDefFoundError is a runtime error, so it’s beyond our application scope to anticipate and recover from this.
  • java.lang.NoClassDefFoundError is a runtime error, it never comes in compile time.
  • It’s very easy to debug NoClassDefFoundError because it clearly says that JVM was unable to find the required class, so check classpath configurations to make sure required classes are not missed.

NoClassDefFoundError Class Diagram

Below image shows NoClassDefFoundError class diagram and it’s super classes. java lang NoClassDefFoundError Class DiagramAs you can see that it’s super classes are Throwable and Error .

java.lang.NoClassDefFoundError Reasons

Let’s first try to replicate a scenario where we get NoClassDefFoundError at runtime. Let’s say we have a java classes like below.

Notice that above class doesn’t depend on any other custom java classes, it just uses java built-in classes. Let’s create another class that will use Data class in the same directory.

Now let’s compile DataTest class and then execute it like below.

So far everything is fine, now let’s move Data class files to somewhere else and then try to execute DataTest class. We will not compile it again since then it will give compilation error.

Here it is, we got NoClassDefFoundError because java runtime is unable to find Data class as clearly shown in the exception stack trace. Below image shows all the above commands and output in the terminal window. java.lang.NoClassDefFoundError example

How to resolve java.lang.NoClassDefFoundError?

From above example, we can clearly identify that the only reason for this error is that the required classes were available at compile time but not at runtime. You can fix NoClassDefFoundError error by checking following:

Check the exception stack trace to know exactly which class throw the error and which is the class not found by java.

Next step is to look for classpath configuration, sometimes we compile our classes in Eclipse or some other environment and run in some other environment and we can miss classpath configurations. For example, I can fix above issue easily by adding the directory which contains Data class to the classpath like below.

Remember that earlier I had moved Data class to previous directory.

Most of the times, NoClassDefFoundError comes with applications running on some server as web application or web services, in that case check if the required jars are part of the WAR file or not. For example, below maven configuration will not package jar file when generating WAR file.

But we need it for creating a servlet based web application, usually this jar is always part of Tomcat or any other application server.

That’s all for a quick look at java.lang.NoClassDefFoundError , I hope you find enough idea when this error comes and how to fix it easily. Reference: API Doc, Exception Handling in Java

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Lesson: Common Problems (and Their Solutions)

If you receive this error, Windows cannot find the compiler ( javac ).

Here's one way to tell Windows where to find javac . Suppose you installed the JDK in C:\jdk1.8.0 . At the prompt you would type the following command and press Enter:

If you choose this option, you'll have to precede your javac and java commands with C:\jdk1.8.0\bin\ each time you compile or run a program. To avoid this extra typing, consult the section Updating the PATH variable in the JDK 8 installation instructions.

Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested

If you receive this error, you forgot to include the .java suffix when compiling the program. Remember, the command is javac HelloWorldApp.java not javac HelloWorldApp .

Common Error Messages on UNIX Systems

javac: Command not found

If you receive this error, UNIX cannot find the compiler, javac .

Here's one way to tell UNIX where to find javac . Suppose you installed the JDK in /usr/local/jdk1.8.0 . At the prompt you would type the following command and press Return:

Note: If you choose this option, each time you compile or run a program, you'll have to precede your javac and java commands with /usr/local/jdk1.8.0/ . To avoid this extra typing, you could add this information to your PATH variable. The steps for doing so will vary depending on which shell you are currently running.

Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested

If you receive this error, you forgot to include the .java suffix when compiling the program. Remember, the command is javac HelloWorldApp.java not javac HelloWorldApp .

Syntax Errors (All Platforms)

If you mistype part of a program, the compiler may issue a syntax error. The message usually displays the type of the error, the line number where the error was detected, the code on that line, and the position of the error within the code. Here's an error caused by omitting a semicolon ( ; ) at the end of a statement:

If you see any compiler errors, then your program did not successfully compile, and the compiler did not create a .class file. Carefully verify the program, fix any errors that you detect, and try again.

Semantic Errors

In addition to verifying that your program is syntactically correct, the compiler checks for other basic correctness. For example, the compiler warns you each time you use a variable that has not been initialized:

Again, your program did not successfully compile, and the compiler did not create a .class file. Fix the error and try again.

Runtime Problems

Error Messages on Microsoft Windows Systems

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp

If you receive this error, java cannot find your bytecode file, HelloWorldApp.class .

One of the places java tries to find your .class file is your current directory. So if your .class file is in C:\java , you should change your current directory to that. To change your directory, type the following command at the prompt and press Enter:

The prompt should change to C:\java> . If you enter dir at the prompt, you should see your .java and .class files. Now enter java HelloWorldApp again.

If you still have problems, you might have to change your CLASSPATH variable. To see if this is necessary, try clobbering the classpath with the following command.

Now enter java HelloWorldApp again. If the program works now, you'll have to change your CLASSPATH variable. To set this variable, consult the Updating the PATH variable section in the JDK 8 installation instructions. The CLASSPATH variable is set in the same manner.

Could not find or load main class HelloWorldApp.class

A common mistake made by beginner programmers is to try and run the java launcher on the .class file that was created by the compiler. For example, you'll get this error if you try to run your program with java HelloWorldApp.class instead of java HelloWorldApp . Remember, the argument is the name of the class that you want to use, not the filename.

Exception in thread "main" java.lang.NoSuchMethodError: main

The Java VM requires that the class you execute with it have a main method at which to begin execution of your application. A Closer Look at the «Hello World!» Application discusses the main method in detail.

Error Messages on UNIX Systems

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp

If you receive this error, java cannot find your bytecode file, HelloWorldApp.class .

One of the places java tries to find your bytecode file is your current directory. So, for example, if your bytecode file is in /home/jdoe/java , you should change your current directory to that. To change your directory, type the following command at the prompt and press Return:

If you enter pwd at the prompt, you should see /home/jdoe/java . If you enter ls at the prompt, you should see your .java and .class files. Now enter java HelloWorldApp again.

If you still have problems, you might have to change your CLASSPATH environment variable. To see if this is necessary, try clobbering the classpath with the following command.

Now enter java HelloWorldApp again. If the program works now, you'll have to change your CLASSPATH variable in the same manner as the PATH variable above.

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp/class

A common mistake made by beginner programmers is to try and run the java launcher on the .class file that was created by the compiler. For example, you'll get this error if you try to run your program with java HelloWorldApp.class instead of java HelloWorldApp . Remember, the argument is the name of the class that you want to use, not the filename.

Exception in thread "main" java.lang.NoSuchMethodError: main

The Java VM requires that the class you execute with it have a main method at which to begin execution of your application. A Closer Look at the «Hello World!» Application discusses the main method in detail.

Applet or Java Web Start Application Is Blocked

If you are running an application through a browser and get security warnings that say the application is blocked, check the following items:

Verify that the attributes in the JAR file manifest are set correctly for the environment in which the application is running. The Permissions attribute is required. In a NetBeans project, you can open the manifest file from the Files tab of the NetBeans IDE by expanding the project folder and double-clicking manifest.mf.

Verify that the application is signed by a valid certificate and that the certificate is located in the Signer CA keystore.

If you are running a local applet, set up a web server to use for testing. You can also add your application to the exception site list, which is managed in the Security tab of the Java Control Panel.

Ошибка 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 :

./862ff58c14b49a983ebc12f5e8e8a6f4.png

В обоих случаях выводится одна и та же трассировка стека:

Чтобы устранить ошибку в обоих сценариях (отсутствующие зависимости и несоответствие версий), нам нужно добавить правильные зависимости. В случае с Junit4 правильными зависимостями являются junit-4.13.2.jar и hamcrest-core-1.3.jar . Добавление этих двух банок в зависимости (ссылочные библиотеки) устраняет ошибку. Инструкции по добавлению и удалению внешних jar-файлов в VS Code присутствуют здесь . Раздел библиотеки, на который мы ссылаемся, должен быть настроен как:

4. Затмение​

В среде Eclipse IDE, которая поддерживает Java 9 и выше, у нас есть путь к классам и путь к модулю. Чтобы разрешить зависимость модуля, мы используем путь к модулю. Однако добавление внешних jar-файлов в путь к модулю не делает их доступными для загрузчика классов . Следовательно, загрузчик классов считает их отсутствующими зависимостями и выдает ошибку NoClassDefFoundError .

Следовательно, если наша зависимость выглядит так, как показано на изображении ниже, выполнение тестового примера Junit приводит к NoClassDefFoundError:

./59b911c40f6cd58786077157e86e4723.png

Трассировка стека, сгенерированная при выполнении теста JUnit, выглядит следующим образом:

В Eclipse нам нужно добавить jar-файлы в путь к классам, а не в путь к модулю. Итак, чтобы правильно добавить внешние банки, следуйте по пути:

щелкните правой кнопкой мыши проект — > Путь сборки — > Настроить путь сборки

В открывшемся окне удалите банки из-под пути к модулю и добавьте их в путь к классам. Это устраняет NoClassDefFoundError . Правильный путь к классам для запуска JUnit должен быть похож на:

./c23dc5d91eb7b5c7b56ea39daefe2505.png

5. Интеллидж​

Для запуска тестовых случаев JUnit 5 требуется как механизм Jupiter, так и API Jupiter. Механизм Jupiter внутренне зависит от API Jupiter, поэтому в большинстве случаев достаточно добавить только зависимость механизма Jupiter в pom.xml. Однако добавление только зависимости API Jupiter в наш pom.xml и отсутствие зависимости механизма Jupiter приводит к NoClassDefFoundError .

Неправильная настройка в pom.xml будет выглядеть так:

Запуск простого тестового примера с этой настройкой приводит к следующей трассировке стека:

В IntelliJ для исправления зависимостей нам нужно исправить pom.xml . Исправленный pom.xml выглядит так:

В качестве альтернативы мы можем добавить junit-jupiter-engine, поскольку его добавление автоматически добавляет jar junit-jupiter-api в путь к классам и устраняет ошибку.

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

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