매니페스트 파일의 메인 클래스가 아닌 Jar에서 클래스를 실행하는 방법


166

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'는 명령 행 인수입니다.


의존성을 유지하기 위해 다른 항아리를 사용하여 다른 항아리에 포장하면됩니까?
Nick

11
커맨드 라인 인수를 기반으로 특정 메소드를 호출하는 단일 메인 클래스가없는 이유는 무엇입니까?
말할 수 없다

답변:


215

매니페스트 파일에서 메인 클래스없이 항아리를 만들 수 있습니다. 그런 다음 :

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

2
문서에 따르면 작동하지 않습니다. "이 옵션이 작동하려면 JAR 파일의 매니페스트에 Main-Class : classname 형식의 줄이 포함되어 있어야합니다."
Thomas

"MyJar.jar에서 메인 클래스 매니페스트 속성을로드하지 못했습니다"
Bhushan

10
토마스가 맞아 "-jar"를 "-cp"로 바꿔야합니다. 업데이트 된 코드보기
lxu4net 3:30의

9
@chrisdew가 제공하는 답변은 Main-Class 속성을 수정 / 제거하여 Jar 파일을 변경하지 않고도 작동합니다.
Ed Griebel

155

jar 파일에 정의 된 경우에도 JAR 파일 의 메소드 가있는 모든 클래스를 실행할 수 있습니다 .public final static mainMain-Class

메인 클래스 실행 :

java -jar MyJar.jar  // will execute the Main-Class

public static void main메소드를 사용하여 다른 클래스를 실행하십시오 .

java -cp MyJar.jar com.mycomp.myproj.AnotherClassWithMainMethod

참고 : 첫 번째는 -jar, 두 번째는을 사용합니다 -cp.


10
그리고 클래스 경로의 현재 디렉토리에있는 모든 jar를 원한다면 (예 : lib 디렉토리에서 Main 클래스를 실행) 유닉스 머신이 확장하지 못하게 java -cp "./*" com.mycomp.myproj.AnotherClassWithMainMethod하는 데 큰 따옴표를 사용할 수 있습니다 ./*. 또한 "./*.jar"작동하지 않습니다.
Petr Újezdský

19

을 호출하는 것 외에도 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);

    }
}

1
이것은 좋은 대안 방법입니다! 내 항아리는 "spring-boot : repackage"를 사용하여 만들었으므로 "-cp"방식으로 다른 입구 클래스를 실행할 수 없습니다. 스프링 부트 플러그인이 항아리에 무엇을했는지 모르겠습니다. 이 경우 디스패치 클래스가 도움이됩니다.
Zhou

6

이 답변은 스프링 부트 사용자를위한 것입니다.

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


항아리가 실행 가능한 경우 어떻게해야합니까? 즉, jar 압축을 풀면 모든 클래스 앞에 "/ BOOT-INF / classes /"
slashdottir

2

우선 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 ...대신 시도해보십시오 . -cpjar를 클래스 경로에 설정하고 java가 기본 클래스를 조회 할 수있게합니다.



1
해당 페이지에서 : "jar 파일을 작성하거나 업데이트하는 동안 사용할 수 있습니다." -이것은 jar를 실행하지 않고 기본 클래스 속성을 설정하는 데 사용됩니다.
Thomas

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


-4

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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.