Несколько выполняемых классов внутри JAR, как их запустить?

#java #jar

#java #jar

Вопрос:

У меня возникли проблемы с запуском нескольких разных классов из одного файла JAR. Я знаю, что могу установить для одного из классов внутри JAR значение by Main class, которое будет запускаться после команды java -jar myjar.jar , но я хочу что-то вроде:

 java -jar myjar.jar MyClass
  

Возможно ли это сделать таким образом, или мне нужно создать несколько JAR (каждый для одного выполняемого класса), или лучше создать класс ‘manager’, который будет запускать мои другие классы, передавая им аргументы командной строки?
Я искал документацию или ссылку, но не смог их найти.

Ответ №1:

Формат исполняемого файла Jar позволяет указать только один основной класс. Для того, чтобы вы могли запускать разные приложения, вам нужно либо создать «manager», как вы предлагаете, либо использовать вместо этого classpath:

 java -cp myjar.jar MyClass
  

Однако этот подход будет игнорировать путь к классу, который вы настроили в файле манифеста Jar.

Комментарии:

1. Игнорирование пути к классу внутри манифеста было одной из моих проблем. Но я протестировал это решение, и, похоже, оно работает (но я не знаю, почему на самом деле, потому что я установил classpath внутри manifest)

2. Это потому, что эта форма запуска не утруждает себя чтением манифеста. Манифест читается только формой -jar.

Ответ №2:

вам придется использовать:

 java -cp myjar.jar MyClass
  

и

 java -cp myjar.jar OtherMainClass
  

Комментарии:

1. Как мне передать несколько аргументов. Я имею в виду, когда я передаю один аргумент, он работает java -cp myjar.jar Другой основной класс foo, но java -cp myjar.jar Другой основной класс foo bar не работает. Принимает только первый аргумент foo .

Ответ №3:

Не лучше ли было бы использовать основной класс «Launcher», функция которого заключается просто в отправке вызовов фактическим классам контроллеров, и использовать файл ссылки в качестве окончательной оболочки, вместо того, чтобы возиться с опцией -cp wm?

В Windows это на удивление легко сделать.

«Основной класс» не должен быть чем-то особо сложным, что-то вроде

 /**
 * Sample launcher
 */
public class Launcher {
    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        if (args != null amp;amp; 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);
            }
        }
    }
}
  

Со стороны Windows достаточно чего-то вроде создания ссылки такого рода

 javaw.exe -jar "jarfile" "a"
  

Это очень полезно для размещения ссылки в папке «sendTo»… один скрытый jar, вызываемый множеством ссылок, которые активируют один из его аспектов, упрощает развертывание обновлений логики jar.

Фактически выбранные файлы передаются в виде списка строк после параметров в определении ссылки.

Таким образом, вам не следует беспокоиться обо всех проблемах с classpath.

Ответ №4:

Вы делаете это следующим образом:

 java -cp myjar.jar MyClass
  

т. е. поместите JAR в classpath, тогда любой класс с методом main может быть запущен путем указания его полного имени. -jar Опция существует только как ярлык для использования информации в манифесте JAR вместо этого (который также может включать другие JAR в classpath, а также указывать основной класс).

Ответ №5:

Файлы Jar могут содержать только один атрибут основного класса в манифесте, что означает, java -jar myjar.jar что они могут запускать только один класс.

Вы можете запускать другие выполняемые классы с

 java -cp myjar.jar OtherClass
  

но это не будет поддерживать двойной щелчок пользователей по файлу jar.

В зависимости от того, насколько опытны ваши пользователи, возможно, им подойдет командная строка. Если нет, вы можете создать скрипт для каждого выполняемого класса или один скрипт, который принимает аргументы для выбора правильного класса.

Ответ №6:

Поскольку был предоставлен правильный ответ, существует решение, которое вы могли бы использовать для создания заглушки jar для каждого основного класса с разными манифестами. Это позволило бы вам создавать выполняемые файлы jar, разрешив двойной щелчок для каждой отдельной программы.

Существует несколько способов достижения этого, но основы заключаются в том, чтобы создать один класс, подобный следующему, который вызывает предполагаемый основной метод, передавая аргументы.

 package com.acme.myapp;

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

Что касается упаковки этого, одним из способов использования maven было бы использование maven-assembly-plugin:jar-with-dependencies mojo. Преимущество здесь в том, что mojo создаст jar для целевого метода main, который является автономным и не нуждается в других сборках в classpath . Это делается путем копирования содержимого каждого jar зависимостей в результирующий jar.