Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run a class from Jar which is not the Main-Class in its Manifest file

People also ask

How do I run a specific class in a jar file?

To run an application in a nonexecutable JAR file, we have to use -cp option instead of -jar. We'll use the -cp option (short for classpath) to specify the JAR file that contains the class file we want to execute: java -cp jar-file-name main-class-name [args …]

Can I build a jar without a main class?

Yes, but since it is a library this class will be available in it too.

How do you fix no main manifest attribute in App jar?

You might get this error when the Main-Class entry is missing in MANIFEST. MF file. You can put the maven-jar-plugin plugin in pom. xml to fix it.


You can create your jar without Main-Class in its Manifest file. Then :

java -cp MyJar.jar com.mycomp.myproj.dir2.MainClass2 /home/myhome/datasource.properties /home/myhome/input.txt

You can execute any class which has a public final static main method from a JAR file, even if the jar file has a Main-Class defined.

Execute Main-Class:

java -jar MyJar.jar  // will execute the Main-Class

Execute another class with a public static void main method:

java -cp MyJar.jar com.mycomp.myproj.AnotherClassWithMainMethod

Note: the first uses -jar, the second uses -cp.


Apart from calling java -jar myjar.jar com.mycompany.Myclass, you can also make the main class in your Manifest a Dispatcher class.

Example:

public class Dispatcher{

    private static final Map<String, Class<?>> ENTRY_POINTS =
        new HashMap<String, Class<?>>();
    static{
        ENTRY_POINTS.put("foo", Foo.class);
        ENTRY_POINTS.put("bar", Bar.class);
        ENTRY_POINTS.put("baz", Baz.class);
    }

    public static void main(final String[] args) throws Exception{

        if(args.length < 1){
            // throw exception, not enough args
        }
        final Class<?> entryPoint = ENTRY_POINTS.get(args[0]);
        if(entryPoint==null){
            // throw exception, entry point doesn't exist
        }
        final String[] argsCopy =
            args.length > 1
                ? Arrays.copyOfRange(args, 1, args.length)
                : new String[0];
        entryPoint.getMethod("main", String[].class).invoke(null,
            (Object) argsCopy);

    }
}

This answer is for Spring-boot users:

If your JAR was from a Spring-boot project and created using the command mvn package spring-boot:repackage, the above "-cp" method won't work. You will get:

Error: Could not find or load main class your.alternative.class.path

even if you can see the class in the JAR by jar tvf yours.jar.

In this case, run your alternative class by the following command:

java -cp yours.jar -Dloader.main=your.alternative.class.path org.springframework.boot.loader.PropertiesLauncher

As I understood, the Spring-boot's org.springframework.boot.loader.PropertiesLauncher class serves as a dispatching entrance class, and the -Dloader.main parameter tells it what to run.

Reference: https://github.com/spring-projects/spring-boot/issues/20404


First of all jar creates a jar, and does not run it. Try java -jar instead.

Second, why do you pass the class twice, as FQCN (com.mycomp.myproj.dir2.MainClass2) and as file (com/mycomp/myproj/dir2/MainClass2.class)?

Edit:

It seems as if java -jar requires a main class to be specified. You could try java -cp your.jar com.mycomp.myproj.dir2.MainClass2 ... instead. -cp sets the jar on the classpath and enables java to look up the main class there.


Another similar option that I think Nick briefly alluded to in the comments is to create multiple wrapper jars. I haven't tried it, but I think they could be completely empty other than the manifest file, which should specify the main class to load as well as the inclusion of the MyJar.jar to the classpath.

MyJar1.jar\META-INF\MANIFEST.MF

Manifest-Version: 1.0
Main-Class: com.mycomp.myproj.dir1.MainClass1
Class-Path: MyJar.jar

MyJar2.jar\META-INF\MANIFEST.MF

Manifest-Version: 1.0
Main-Class: com.mycomp.myproj.dir2.MainClass2
Class-Path: MyJar.jar

etc. Then just run it with java -jar MyJar2.jar