How to Troubleshoot java.lang.NoClassDefFoundError: org/apache/log4j/Level

Amar Gurung
Zaloni Engineering
Published in
2 min readSep 8, 2021

Introduction

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 )

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.conf.Configuration;
public static void main(String args[]){
.....
Configuration config = new Configuration();
FileSystem localFileSystem = FileSystem.getLocal(config);
......
}

Exception Stack Trace

Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/Level
at org.apache.hadoop.mapred.JobConf.<clinit>(JobConf.java:351)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.apache.hadoop.conf.Configuration.getClassByNameOrNull(Configuration.java:2247)
at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:95)
at org.apache.hadoop.util.ReflectionUtils.setConf(ReflectionUtils.java:78)
at org.apache.hadoop.util.ReflectionUtils.newInstance(ReflectionUtils.java:136)
at org.apache.hadoop.security.Groups.<init>(Groups.java:102)
at org.apache.hadoop.security.Groups.<init>(Groups.java:97)
at org.apache.hadoop.security.Groups.getUserToGroupsMappingService(Groups.java:463)
at org.apache.hadoop.security.UserGroupInformation.initialize(UserGroupInformation.java:328)
at org.apache.hadoop.security.UserGroupInformation.ensureInitialized(UserGroupInformation.java:295)
at org.apache.hadoop.security.UserGroupInformation.loginUserFromSubject(UserGroupInformation.java:850)
at org.apache.hadoop.security.UserGroupInformation.getLoginUser(UserGroupInformation.java:820)
at org.apache.hadoop.security.UserGroupInformation.getCurrentUser(UserGroupInformation.java:693)
at org.apache.hadoop.fs.FileSystem$Cache$Key.<init>(FileSystem.java:2953)
at org.apache.hadoop.fs.FileSystem$Cache$Key.<init>(FileSystem.java:2943)
at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2809)
at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:389)
at org.apache.hadoop.fs.FileSystem.getLocal(FileSystem.java:360)

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

import org.apache.log4j.Level;

@InterfaceAudience.Public
@InterfaceStability.Stable
public class JobConf extends Configuration {

private static final Log LOG = LogFactory.getLog(JobConf.class);

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@InterfaceAudience.Public
@InterfaceStability.Stable
public class JobConf
extends Configuration
{
private static final Logger LOG = LoggerFactory.getLogger(JobConf.class);

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.

$ jar tvf log4j-1.2-api-2.8.jar | grep "Logger"
1034 Sun Jan 22 05:24:58 IST 2017 org/apache/log4j/Logger$PrivateManager.class
1880 Sun Jan 22 05:24:58 IST 2017 org/apache/log4j/Logger.class
208 Sun Jan 22 05:24:58 IST 2017 org/apache/log4j/spi/LoggerFactory.class
914 Sun Jan 22 05:24:58 IST 2017 org/apache/log4j/spi/LoggerRepository.class

Resolution:

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

Conclusion

In this blog, readers walked through the java.lang.NoClassDefFoundError , how and why issue cropped up and resolution of the issue.

--

--