Multiple runnable classes inside JAR, how to run them?
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 t开发者_JS百科his 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.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.
you will have to use:
java -cp myjar.jar MyClass
and
java -cp myjar.jar OtherMainClass
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).
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.
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.
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.
精彩评论