簡體   English   中英

如何從 Jar 運行一個不在其 Manifest 文件中的 Main-Class 的類

[英]How to run a class from Jar which is not the Main-Class in its Manifest file

我有一個包含 4 個類的 JAR,每個類都有 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' 是命令行參數)。

您可以在其 Manifest 文件中創建沒有 Main-Class 的 jar。 然后 :

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

您可以從 JAR 文件執行任何具有public static void main方法的類,即使 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 tvf yours.jar看到 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之外,您還可以將 Manifest 中的主類設為 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);

    }
}

我認為尼克在評論中簡要提到的另一個類似選項是創建多個包裝罐。 我沒有嘗試過,但我認為除了清單文件之外它們可能是完全空的,清單文件應該指定要加載的主類以及將 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運行它

首先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 並使 java 能夠在那里查找主類。

在pom.xml文件中添加以下插件,並在element中指定具有完全限定名稱的Main Class。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM