web-dev-qa-db-fra.com

Comment exécuter une classe à partir de Jar qui n'est pas la classe principale dans son fichier manifeste

J'ai un fichier JAR avec 4 classes, chacune ayant la méthode Main. Je veux être en mesure de gérer chacun d'entre eux selon les besoins. J'essaye de l'exécuter en ligne de commande sous Linux.

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

Il a une structure de répertoire pour les classes principales comme suit:

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

Je sais que je peux spécifier une classe comme principale dans mon fichier Manifest. Mais y a-t-il un moyen par lequel je peux spécifier un argument sur la ligne de commande pour exécuter la classe que je souhaite exécuter?

J'ai essayé ceci:

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

Et j'ai eu cette erreur:

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

(Dans la commande ci-dessus, '/home/myhome/datasource.properties' et '/home/myhome/input.txt' sont les arguments de la ligne de commande).

137
Bhushan

Vous pouvez créer votre pot sans classe principale dans son fichier manifeste. Ensuite :

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

Vous pouvez exécuter la classe n'importe laquelle qui a une méthode public final static main à partir d'un fichier JAR, même si le fichier jar a un Main-Class défini.

Exécuter la classe principale:

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

Exécutez une autre classe avec une méthode public static void main:

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

Remarque: le premier utilise -jar, le second utilise -cp.

116
fadedbee

En plus d'appeler Java -jar myjar.jar com.mycompany.Myclass, vous pouvez également transformer la classe principale de votre classe Manifest en classe Dispatcher.

Exemple:

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

    }
}
15
Sean Patrick Floyd

Tout d'abord, jar crée un fichier jar et ne l'exécute pas. Essayez Java -jar à la place.

Deuxièmement, pourquoi passez-vous la classe deux fois, en tant que FQCN (com.mycomp.myproj.dir2.MainClass2) et en tant que fichier (com/mycomp/myproj/dir2/MainClass2.class)?

Modifier:

Il semble que Java -jar nécessite la spécification d'une classe principale. Vous pouvez essayer Java -cp your.jar com.mycomp.myproj.dir2.MainClass2 ... à la place. -cp définit le fichier jar sur le chemin de classe et permet à Java de rechercher la classe principale à cet endroit.

2
Thomas

Une autre option similaire que Nick a brièvement évoquée dans les commentaires consiste à créer plusieurs bocaux. Je ne l'ai pas essayé, mais je pense qu'ils pourraient être complètement vides, à l'exception du fichier manifeste, qui devrait spécifier la classe principale à charger ainsi que l'inclusion du fichier MyJar.jar dans le chemin d'accès aux classes.

MyJar 1. Jar\META-INF\MANIFEST.MF

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

MyJar 2. Jar\META-INF\MANIFEST.MF

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

etc. Ensuite, lancez-le avec Java -jar MyJar2.jar

1
JSub