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

I have a JAR with 4 classes, each one has Main method. I want to be able to run each one of those as per the need. I am trying to run it from command-line on Linux box.

E.g. The name of my JAR is MyJar.jar

It has directory structure for the main classes as follows:

com/mycomp/myproj/dir1/MainClass1.class
com/mycomp/myproj/dir2/MainClass2.class
com/mycomp/myproj/dir3/MainClass3.class
com/mycomp/myproj/dir4/MainClass4.class

I know that I can specify one class as main in my Manifest file. But is there any way by which I can specify some argument on command line to run whichever class I wish to run?

I tried this:

jar cfe MyJar.jar com.mycomp.myproj.dir2.MainClass2 com/mycomp/myproj/dir2/MainClass2.class /home/myhome/datasource.properties /home/myhome/input.txt

And I got this error:

com/mycomp/myproj/dir2/MainClass2.class : no such file or directory

(In the above command, '/home/myhome/datasource.properties' and '/home/myhome/input.txt' are the command line arguments).

This question is related to java jar executable-jar

The answer is


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);

    }
}

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


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.


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.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to jar

Running JAR file on Windows 10 Add jars to a Spark Job - spark-submit Deploying Maven project throws java.util.zip.ZipException: invalid LOC header (bad signature) java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory Maven Error: Could not find or load main class Where can I download mysql jdbc jar from? Access restriction: The type 'Application' is not API (restriction on required library rt.jar) Create aar file in Android Studio Checking Maven Version Creating runnable JAR with Gradle

Examples related to executable-jar

Running JAR file on Windows 10 How do I tell Spring Boot which main class to use for the executable jar? Reference jars inside a jar Run java jar file on a server as background process What causes "Unable to access jarfile" error? "Could not find the main class" error when running jar exported by Eclipse how to check the version of jar file? How to run a class from Jar which is not the Main-Class in its Manifest file How to make an executable JAR file? how to run or install a *.jar file in windows?