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

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

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" являются аргументами командной строки).

6 ответов

Решение

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

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

Вы можете выполнить любой класс, который имеет 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,

Этот ответ предназначен для пользователей Spring-boot:

Если ваш JAR был от Spring-boot проект и создан с помощью команды mvn package spring-boot:repackage, указанный выше метод "-cp" не будет работать. Ты получишь:

Ошибка: не удалось найти или загрузить основной класс your.alternative.class.path

даже если вы можете увидеть класс в JAR jar tvf yours.jar.

В этом случае запустите альтернативный класс с помощью следующей команды:

java -cp yours.jar -Dloader.main=your.alternative.class.path org.springframework.boot.loader.PropertiesLauncher

Как я понял, у Spring-boot org.springframework.boot.loader.PropertiesLauncher класс служит диспетчерским входным классом, а -Dloader.main параметр указывает, что запускать.

Ссылка: https://github.com/spring-projects/spring-boot/issues/20404

Помимо звонка 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);

    }
}

Еще одна похожая опция, на которую, как мне кажется, Ник кратко упомянул в комментариях, - это создание нескольких jar-пакетов. Я не пробовал, но я думаю, что они могут быть полностью пустыми, кроме файла манифеста, в котором должен быть указан основной класс для загрузки, а также включение MyJar.jar в 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

и т.д. Тогда просто запустите его с java -jar MyJar2.jar

Прежде всего 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 на classpath и позволяет java искать там основной класс.

Добавьте плагин ниже в ваш файл 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>
Другие вопросы по тегам