Multiple runnable classes inside JAR, how to run them?

JavaJar

Java Problem Overview


I'm having problems with running multiple different classes from one JAR file. I know that I can set one of the classes inside JAR to by Main class that will be run after command java -jar myjar.jar, but what I want is something like:

java -jar myjar.jar MyClass

Is it possible to do this that way, or do I have to create multiple JAR (each for one runnable class), or is it better to create 'manager' class that will run my other classes passing to them command line arguments?
I was looking for documentation or reference, but I couldn't find any.

Java Solutions


Solution 1 - Java

The executable Jar file format only allows you to specify one main class. In order for you to be able to execute different applications, you'll need to either create a "manager" as you suggest, or to use the classpath instead:

java -cp myjar.jar MyClass

However, this approach will ignore the classpath you have configured in the Jar's manifest file.

Solution 2 - Java

you will have to use:

java -cp myjar.jar MyClass

and

java -cp myjar.jar OtherMainClass

Solution 3 - Java

You do it like this:

java -cp myjar.jar MyClass

i.e. put the JAR into the classpath, then any class with a main method can be run by specifying its fully qualified name. The -jar option only exists as a shortcut to use the information in the JAR's manifest instead (which can also include other JARs in the classpath as well as specify the main class).

Solution 4 - Java

Wouldn't you be better served with using a "Launcher" main class, whose function is just to dispatch the calls to the actual controller classes, and using a link file as a final wrapper, instead of fiddling with the -cp option of the wm?

In windows, it is surprisingly easy to do so.

The "main class" needs not be anything much complex, something like

/**
 * Sample launcher
 */
public class Launcher {
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		if (args != null && args.length > 0) {
			String option= args[0]; 
			String[] args2=new String[0];   			
			
			if( args.length>1){
				args2= new String[args.length-1];
				System.arraycopy(args, 1, args2, 0, args2.length); 
			}
			
			if(option.equals("a")) {
				new ClassA().exec(args2);
            }
			else if(option.equals("b")){ 				
				new ClassB().exec(args2);
            }
		}
	}
}

On the windows side of things, it is enough something like creating a link of this kind

javaw.exe -jar "jarfile" "a"

It is very useful for placing link in the "sendTo" folder... one jar, hidden, called by many links that activate one of its aspects makes simpler to deploy updates of the jar logic.

The actual files selected are passed as a list of string after the params in the link definition.

This way, you should not worry about the whole classpath issues.

Solution 5 - Java

As the correct answer has been provided there is a solution that you could use to build a stub jar for each main class with different manifests. This would allow you to create runnable jar files by allowing double-clicking for each separate program.

There are several ways of accomplishing this but the basics are to put a single class similar to the following which invokes the intended main method passing args.

package com.acme.myapp;

public final class Stub1 {
    public static void main(String[] args) {
        App1.main(args);
    }
}

As for packaging this, one way using maven would be with the maven-assembly-plugin:jar-with-dependencies mojo. The advantage here is that the mojo will build a jar for the target main method that is self contained and does not need to have other assemblies on the classpath. It does this by copying the contents of each dependency jar into the resultant jar.

Solution 6 - Java

Jar files can contain only one Main-Class attribute in the manifest, which means java -jar myjar.jar can only start one class.

You can start other runnable classes with

java -cp myjar.jar OtherClass

but that won't support users double-clicking on the jar file.

Depending on how skilled your users are, maybe the command line is OK for them. If not, you can create a script for each runnable class or one script that takes arguments to choose the right class.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwlkView Question on Stackoverflow
Solution 1 - JavaiggymoranView Answer on Stackoverflow
Solution 2 - JavaGareth DavisView Answer on Stackoverflow
Solution 3 - JavaMichael BorgwardtView Answer on Stackoverflow
Solution 4 - JavaDBZView Answer on Stackoverflow
Solution 5 - JavaBrett RyanView Answer on Stackoverflow
Solution 6 - JavaCameron SkinnerView Answer on Stackoverflow