Как запустить класс из 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>