Docker error could not find or load main class

Problem

Problem

When we use docker with spring boot projects, sometimes, we get this error:

➜  bin git:(main) ✗ ./docker-run.sh myharbor.com/bswen/spring
Error: Could not find or load main class com.bswen.app7.Main

The core exception is:

Error: Could not find or load main class com.bswen.app7.Main

Environment

  • java 1.8
  • Spring Boot 2.3
  • Intellij IDEA
  • Docker 19

Debug

The Dockerfile:

FROM openjdk:8-jdk-alpine
MAINTAINER [email protected]
ENV APPROOT="/opt/app7"
ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib ${APPROOT}/lib
COPY ${DEPENDENCY}/META-INF ${APPROOT}/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes ${APPROOT}

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-cp","/opt/app8:/opt/app7/lib/*","-Droot.dir=/opt/app7","com.bswen.app7.Main"]
EXPOSE 8082

The Main class of this spring boot application:

package com.bswen.app7;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class,args);
    }
}

If we run the app with gradle directly like this:

It works, and if we run the spring boot docker image directly without kubernetes like this:

We get the error again:

Error: Could not find or load main class com.bswen.app7.Main

Reason

According to the above debug process, we can found that the real problem should be the Dockerfile, it caused the exception in docker environment.

Solution

We found that there is a wrong character in the Dockerfile, which cause the spring boot app starts with a wrong classpath, that’s the key problem, we changed the Dockerfile like this:

FROM openjdk:8-jdk-alpine
MAINTAINER [email protected]
ENV APPROOT="/opt/app7"
ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib ${APPROOT}/lib
COPY ${DEPENDENCY}/META-INF ${APPROOT}/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes ${APPROOT}

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-cp","/opt/app7:/opt/app7/lib/*","-Droot.dir=/opt/app7","com.bswen.app7.Main"]
EXPOSE 8082

Pay attention to the last command in the Dockerfile of this spring boot app:

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-cp","/opt/app7:/opt/app7/lib/*","-Droot.dir=/opt/app7","com.bswen.app7.Main"]
EXPOSE 8082

The wrong configuration is “java … -cp /opt/app8…”, the right configuration is “java … -cp /opt/app7..”, this app is installed in “/opt/app7”, not “/opt/app8”, that’s the key point.

I am new to learning Docker, and followed a tutorial to make a small Hello World application to dockerize. I used Intellij template to generate a main method, which lies in the «com.company» package. All the method does is print out «Hello World!».

The problem is when I try to run the image from the terminal, it gives me this error:

Error: Could not find or load main class src.com.company.Main.java
Caused by: java.lang.ClassNotFoundException: src.com.company.Main.java

I made a Docker file that looks like this:

FROM openjdk:11

RUN mkdir /app

COPY out/production/DockerTestApp/com/company/Main.class/ /app

WORKDIR /app

CMD java src/com/company/Main.java

For the «COPY» path, I just copied the Content Root path of the Main class in the «out» folder.

For the CMD path, I copied the Content Root path in the «src» folder.

This is the command I use to build the image(I give it a new TAG everytime):

docker build -t hello-world:3.0 .

I have tried writing the paths differently and creating the image again, but I just dont understand how Im supposed to write it.

I appreciate your help!

@TomLefley

Steps to reproduce:

  1. Create basic gradle project with docker-java as a compile dependency
  2. Add a simple HelloWorld main class
  3. Run the gradle jar task
  4. java -jar hello-world.jar

Exception thrown at startup is

Error: Could not find or load main class HelloWorld
Caused by: java.lang.ClassNotFoundException: HelloWorld

Removing docker-java from compile dependencies fixes the issue.

Example build.gradle

dependencies {
    compile(
            "com.github.docker-java:docker-java:3.0.14"
    )
}

task helloWorld(type: Jar) {
    manifest {
        attributes 'Main-Class': 'HelloWorld'
    }
    baseName = 'hello-world'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

Reproduced with jdk8, jdk9, jdk10
Tested with docker-java versions 3.0.6, 3.0.14, 3.1.0-rc-4

@TomLefley

A workaround we’ve found for this is to build a skinny jar with the dependencies on the classpath rather than bundling everything into a fat jar.

@sedovalx

I have exactly the same issue. After including the docker-java as a compile dependency java can’t load my main class from the fat jar with a SecurityException «Invalid signature file digest for Manifest main attributes». Actually the same happens when I try to add the docker-client library. The reason was that the library’s signature files were copied into the META-INF of my fat jar and it broke class loading of my main class. Here is the fix:

    jar {
        manifest {
            attributes(
                "Main-Class" to "sandbox.MainKt"
            )
        }
        from(configurations.compile.get().map { if (it.isDirectory) it else zipTree(it) })
        from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
        exclude("META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA")
    }

@dwgabriel

@sedovalx I’m facing this same exact problem but I’m new to this, so I’m not sure how would I go about using your fix. Could you elaborate a little on how to implement your fix? Thanks in advance

@sedovalx

@dwgabriel the code fragment above is from my Gradle build script. It describes the configuration of the jar task that can be run with ./gradlew jar. The task assembles an executable jar file that can be executed with java -jar my-app.jar.

Build scripts in Gradle typically named as build.gradle (if written in Groovy) or build.gradle.kts (in case of Kotlin).

@RowDaBoat

Still broken in 3.2.6, same steps to reproduce, add dep. docker-java, build a fat jar, run with java -jar fat.jar:

dependencies {
    ...
    implementation("com.github.docker-java:docker-java:3.2.6")
}

tasks.withType<Jar> {
    manifest { attributes["Main-Class"] = "com.company.application.Main" }

    configurations["compileClasspath"].forEach { file: File ->
        from(zipTree(file.absoluteFile))
    }
}

Is an obscure workaround enough to consider this issue closed?

Java Could Not Find or Load Main Class

When starting your Java application, you may encounter this error:

Error: Could not find or load main class MyClass
Caused by: java.lang.ClassNotFoundException: MyClass
Caused by: java.lang.ClassNotFoundException: MyClass

This error is very common when creating new Java based projects. Whether you’re using Gradle or Maven, Spring Boot or Kafka, chances are you’ve encountered this error before.

Sometimes the error will occur unexpectedly. Sometimes the error is specific to your IDE.

Regardless, fixing the error is easy and it starts with understanding the cause:

What Causes the «Could Not Find or Load Main Class» Error?

This error is thrown whenever Java can’t find or load the main class of your application.

Let’s say you define a class like this:

public class MyClass {
  public static void main(String[] args) {
    System.out.println("My class is working!");
  }
}
  public static void main(String[] args) {
    System.out.println("My class is working!");
  }
}

When running this simple class, you could get the «could not find or load main class» error for several reasons…

1. IDE Configuration Issue

Most IDEs let you configure the starting point for your application. For example, in IntelliJ you can edit configuration to select a main class for running the project.

If you’re running your application through an IDE, make sure that it is configured properly to look for the main class in the right place.

2. Wrong Class Name

Remember that class names must be unique in Java. Furthermore, they are case sensitive…

Let’s say you are running your program from the CLI using the java tool..

java myclass

This will result in the «Could not find or load main class» error because class names are case sensitive.

3. Wrong Extension

When running from the command line, many developers accidentally append an extension like:

java MyClass.java

or

java MyClass.class

The correct way is to run without any extension:

java MyClass

4. Wrong Location

Let’s say your class is part of a package like this:

package com.myproject;
public class  MyClass {
  public static void main(String[] args) {
    System.out.println("My class is working!");
  }
}
public class  MyClass {
  public static void main(String[] args) {
    System.out.println("My class is working!");
  }
}

If you don’t run your class with the fully qualified name AND from the right directory, you will get the «Could not find or load main class» error…

5. Wrong Class Path

The class path is where the JVM looks for classes to load into your program. Sometimes developers provide a specified path like this:

java MyClass -cp /usr/local/path

While the optional -cp argument allows you to specify your own class path, you can easily get the «Could not find or load main class» error if this is incorrect…

How to fix the «Could Not Find or Load Main Class» Error

1. Make sure your IDE is configured properly

Make sure that your IDE has the correct configuration for finding the main class/entry point of your application.

2. Make sure your class name is correct

If you are running your program from the CLI, make sure that you are specifying the right class name without extensions…

java MyClass

3. Make sure you are running your application from the right directory

Make sure you are running your application from the right folder. If your class is part of a package then you must run it from the parent directory….

java com.myproject.MyClass

4. Make sure your class path is correct

Make sure your class path is correct. By default, the class path is the current working directory «.». If you override this with the -cp argument then make sure it’s accurate!

Understanding the Java Error «Could Not Find or Load Main Class»

While this error is self explanatory and easy to fix, it’s worth understanding how Class Loaders work behind the scenes. This gives you a better understanding of why the «Could Not Find or Load Main Class» error happens…

When are Classes Loaded in Java?

Classes are loaded dynamically. This means classes are loaded into memory only when they are needed.

Unlike C++, Java is a dynamically compiled language. This means the language is compiled to machine code while the program is running.

Of course, some classes must be loaded initially when your program starts. The JRE utilizes a native class loader to load the main entry point of your application. From here, class loaders are used to dynamically load (lazy load) classes as they are needed by the application.

The Class Loading Mechanism in Java

Java utilizes a delegation mechanism for loading classes at runtime. There are 3 built-in class loaders used by the JRE at runtime:

1. Bootstrap class loader: This loads the standard runtime classes found in rt.jar

2. Extensions: This loads any extension classes used by the JRE

3. System: This loads classes defined by the application and found on the class path

Each class loader first checks a cache to see if the requested class has already been loaded into memory. If nothing is found in the cache, it delegates the finding of the class to the parent class loader.

This process happens recursively…

If the system class loader can’t find the class, it delegates to the extension class loader.

If the extension class loader can’t find the class, it delegates to the bootstrap class loader.

If the bootstrap class loader can’t find the class, it tells the extension class loader to find it

If the extension class loader can’t find the class, it tells the system class loader to find it

If the system class loader can’t find it, it throws an ClassNotFound exception

This mechanism works to ensure uniqueness, visibility and delegation are applied to the class loading mechanism in Java.

Uniqueness explains the reason why no two classes can have the same name. By keeping class names unique, class loaders can easily find the single representation of a defined class.

Visibility explains the child-parent relationship between class loaders. While children can view parent classes, parents can’t view child classes. This ensures an isolation level needed to create the hierarchy between class loaders.

Delegation explains how the class loaders work together to recursively retrieve a unique class. By delegating to parent classes, class loaders ensure only one representation of a defined class exists.

Java Class Loading Order

1) Class loader searches cache for loaded classes

2) If cache has the class, it is returned. Otherwise, the class loader delegates to parent class to retrieve the class

3) Parent class loaders ultimately delegate to the bootstrap class loader. If the class isn’t found, the bootstrap loader returns responsibility to child loader.

4) Either the system loader finds and loads the class, or a ClassNotFound exception is thrown.

Custom Class Loaders

You can create your own class loaders by extending the ClassLoader class:

public class CustomClassLoader extends ClassLoader { ...

Most developers don’t need to worry about creating custom class loaders. There are times where it makes sense however. Sometimes custom class loaders are used to implementing class versioning. Other custom class loaders allow you to create classes dynamically or switch implementations etc.

Conclusion

The «Could not find or load main class» error is common and easy to fix. Its cause usually has to do with specifying the wrong class name, extension, or class path.

This error can be easily fixed by checking IDE configurations, class path variables, class names, and making sure you’re running the application from the right directory.

The JRE utilizes a class loading mechanism to dynamically load classes into memory. This mechanism relies on a recursive process where class loaders delegate retrieval to parent loaders if they can’t find the class already loaded in memory.

You can create your own custom class loaders for dynamic class creation and versioning.

Your thoughts?

Spring Boot App Program Error: Could not find or load main class

This tutorial guides you on how to resolve Spring Boot App Program Error: Could not find or load main class. Occasionally, we might see error “Could not find or load main class” while running Spring Boot App or any Java Program. Let’s see how to resolve the same.

Spring Boot App Program Error: Could not find or load main class

Well, I have created a Spring Boot Application with necessary changes for my App to run. Note, I have created this Spring Boot project using Spring Boot wizard from Eclipse. After, making necessary changes I tried to run the Spring Boot App using the following option:

Right Click Spring Boot Project in Eclipse -> Run As -> Spring Boot App

But it failed with error “Could not find or load main class”.

Error: Could not find or load main class com.de.sneppets.connectivity.ExampleSpringBootApplication
Caused by: java.lang.ClassNotFoundException: com.de.sneppets.connectivity.ExampleSpringBootApplication

And this is the case you might come across even for other Java Program or Projects.

Fix 1: mvn clean install

First, try building the Spring Boot App and check if that resolves the above issue.

What I did was. I tried to build the Spring Boot App from the command line again.

> mvn clean install

And the Build was successful. After building the code successfully, I tried to run the Spring Boot App again. And I don’t see that error any more. Check if this works for you.

Fix 2: Update Project

This is another way which you could try to resolve main class load error. All that you need to do is Update Maven Project using the following option.

Right Click Spring Boot Project -> Maven -> Update Project

And in the Update Maven Project wizard select the Maven Project that you wanted to update with default update options and click “OK”.

After, you do the above step try running your Spring Boot App. Yay! it worked for me. And I don’t see the error any more.

That’s it. The main reason for the error “Could not find or load main class” is due to compiled classes not found in the target directory. Therefore, we need to follow any one of the above approach to build the code to generate classes, so that your Spring Boot App will run successfully.

Hope this is helpful 🙂

You’ll also like:

  • Add or install local jar files to the Maven Project
  • Build maven project without version
  • Create JWT Token and Sign with RSA Private Key
  • Replace element in ArrayList at specific index
  • Convert Integer List to int array
  • ArrayList removeAll() method not removing elements
  • Convert floating point number to fixed point in Python
  • What is %matplotlib inline and how to use ?
  • Java String substring() example program
  • Add python3 kernel to jupyter IPython notebook ?
  • Reset jupyter notebook theme to default theme
  • Jacoco Maven Plugin Junit Code Coverage Example
  • Assign value to static variables from application.properties in Spring Boot ?
  • Run a Jupyter Notebook .ipynb file from terminal or cmd prompt
  • Websocket connection closed automatically – keepalive Ping example
  • Check if a file or folder exists without getting exceptions ?
  • Python program to find the greatest of three numbers
  • Putty Fatal Error No supported authentication methods available
  • Find which users belongs to a specific group in linux
  • Check if Python Object is a Number ?
  • Remove non-numeric characters from string in Python
  • Convert negative to positive number in Python
  • Extract numbers from a string in python
  • Program to Check Given Number is Odd or Even

References:

  • maven documentation
  • wikipedia

Понравилась статья? Поделить с друзьями:
  • Docker desktop stopping как исправить
  • Docker compose error while fetching server api version
  • Docker compose error log
  • Docker build error during connect
  • Docker 404 error