如何从Jar运行一个类,它不是Manifest文件中的Main-Class

时间:2011-03-29 15:02:16

标签: java jar executable-jar

我有一个包含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

我知道我可以在Manifest文件中指定一个类作为main。但是,有什么方法可以在命令行上指定一些参数来运行我希望运行的任何类?

我试过了:

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'是命令行参数。)

7 个答案:

答案 0 :(得分:163)

您可以在Manifest文件中创建没有Main-Class的jar。然后:

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

答案 1 :(得分:109)

即使jar文件定义了set_Name ,您也可以从JAR文件执行任何具有public final static main方法的类。

执行Main-Class:

Main-Class

使用java -jar MyJar.jar // will execute the Main-Class 方法执行另一个类:

public static void main

注意:第一次使用java -cp MyJar.jar com.mycomp.myproj.AnotherClassWithMainMethod ,第二次使用-jar

答案 2 :(得分:13)

除了调用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);

    }
}

答案 3 :(得分:10)

此答案适用于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

答案 4 :(得分:2)

首先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能够在那里查找主类。

答案 5 :(得分:1)

我认为Nick在评论中简要提到的另一个类似选项是创建多个包装器罐。我没有尝试过,但我认为除了清单文件之外,它们可能是完全空的,清单文件应指定要加载的主类以及将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

运行它

答案 6 :(得分:-2)

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