Как запустить класс из Jar, который не является основным классом в его файле манифеста

У меня есть JAR с 4 классами, каждый из которых имеет метод Main. Я хочу иметь возможность запускать каждый из них по мере необходимости. Я пытаюсь запустить его из командной строки в Linux.

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

Он имеет структуру каталогов для основных классов следующим образом:

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

Я знаю, что я могу указать один класс как основной в моем файле манифеста. Но есть ли способ, с помощью которого я могу указать некоторый аргумент в командной строке для запуска того класса, который я хочу запустить?

Я пробовал это:

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

И я получил эту ошибку:

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

(В приведенной выше команде "/home/myhome/datasource.properties" и "/home/myhome/input.txt" являются аргументами командной строки).

Ответ 1

Вы можете создать свой кувшин без Main-Class в файле Manifest. Затем:

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

Ответ 2

Вы можете выполнить любой класс, который имеет метод public final static main из JAR файла, даже если файл jar имеет Main-Class.

Выполнить основной класс:

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

Выполните другой класс с помощью метода public static void main:

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

Примечание: первая использует -jar, вторая использует -cp.

Ответ 3

Помимо вызова java -jar myjar.jar com.mycompany.Myclass, вы также можете сделать основной класс в своем манифесте класса Dispatcher.

Пример:

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

    }
}

Ответ 4

Прежде всего jar создает банку и не запускает ее. Вместо этого попробуйте java -jar.

Во-вторых, почему вы проходите класс дважды, как FQCN (com.mycomp.myproj.dir2.MainClass2) и как файл (com/mycomp/myproj/dir2/MainClass2.class)?

Изменить:

Кажется, что java -jar требует указания основного класса. Вместо этого вы можете попробовать java -cp your.jar com.mycomp.myproj.dir2.MainClass2 .... -cp устанавливает jar в путь к классам и позволяет java искать основной класс там.

Ответ 5

Другой подобный вариант, который, как мне кажется, кратко упоминается в комментариях, заключается в создании нескольких баннеров-оберток. Я не пробовал, но я думаю, что они могут быть полностью пустыми, кроме файла манифеста, который должен указывать основной класс для загрузки, а также включение MyJar.jar в путь к классам.

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

и т.д.. Затем просто запустите его с помощью java -jar MyJar2.jar

Ответ 7

Добавьте ниже плагин в свой файл pom.xml и укажите основной класс с полным именем в элементе.

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.2.5.RELEASE</version>
    <configuration>
        <mainClass>**main Class name with full qualified name**</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>