티스토리 뷰

Web Development

Runnable Jar (Maven Shade)

§무명소졸§ 2020. 3. 12. 18:19

Maven에서 Java 애플리케이션을 runnable jar 파일로 만드는 방법은 아래와 같이 대략 3가지 방법이 있다.

  • maven-jar-plugin : src/main/java, src/main/resources 만 포함한다.
  • maven-assembling-plugin: depdendencies jar 를 파일들을 함께 모듈화 한다.
  • maven-shade-plugin: depdendencies jar 를 파일을 함께 모듈화 하고 중복되는 클래스가 있을경우 relocate

dependency 모듈들의 packing 과  패키지, 클래스명 중복시 유연한 대처를 위해서 shade 플러그인을 사용하는게 가장 좋다. 오늘은 아주 간단한 자바 애플리케이션으로 Runnable Jar 파일을 만들어보겠다.

pom.xml

maven shade 플러그인과 가장 많이 쓰이는 유틸리티 모듈 중 하나인 apache common dependency를 가지고 있다. 

 <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.2</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>info.m2sj.M2sjMain</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

 

Java Application

stdout 으로 문자열을 출력하는 간단한 자바 프로그램이다. apache common 모듈 StringUtils 클래스 메서드를 이용해서 축약된 문자열을 출력한다.

public static void main(String[] args) {
	String text = "Hello Maven!!";
	System.out.println(text);
	System.out.println(StringUtils.abbreviate(text,5));
}

 

Maven Package

mvn clean package 명령어를 이용해서 Jar를 파일을 만들어보겠다. 우리가 원하는건 org.apache.commons 패키지 모듈과 의존성이 있는 모든 파일들이 한 개의 Jar파일로 함께 만들어지는 것이다.

mvn clean package
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< org.example:shadedtest >-----------------------
[INFO] Building shadedtest 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ shadedtest ---
[INFO] Deleting /Users/mhkim/m2sj_project/shadedtest/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ shadedtest ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ shadedtest ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/mhkim/m2sj_project/shadedtest/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ shadedtest ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/mhkim/m2sj_project/shadedtest/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ shadedtest ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ shadedtest ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ shadedtest ---
[INFO] Building jar: /Users/mhkim/m2sj_project/shadedtest/target/shadedtest-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-shade-plugin:3.2.2:shade (default) @ shadedtest ---
[INFO] Including org.apache.commons:commons-lang3:jar:3.0 in the shaded jar.
[WARNING] commons-lang3-3.0.jar, shadedtest-1.0-SNAPSHOT.jar define 1 overlapping resources: 
[WARNING]   - META-INF/MANIFEST.MF
[WARNING] maven-shade-plugin has detected that some class files are
[WARNING] present in two or more JARs. When this happens, only one
[WARNING] single version of the class is copied to the uber jar.
[WARNING] Usually this is not harmful and you can skip these warnings,
[WARNING] otherwise try to manually exclude artifacts based on
[WARNING] mvn dependency:tree -Ddetail=true and the above output.
[WARNING] See http://maven.apache.org/plugins/maven-shade-plugin/
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing /Users/mhkim/m2sj_project/shadedtest/target/shadedtest-1.0-SNAPSHOT.jar with /Users/mhkim/m2sj_project/shadedtest/target/shadedtest-1.0-SNAPSHOT-shaded.jar
[INFO] Dependency-reduced POM written at: /Users/mhkim/m2sj_project/shadedtest/dependency-reduced-pom.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.068 s
[INFO] Finished at: 2020-03-16T11:55:39+09:00
[INFO] ------------------------------------------------------------------------

 

Run Java

target 디렉토리에 2개의 jar파일이 만들어졌다. prefix 로 original이 붙어있는 jar가 의존성 없이  만들어진 파일이며 origin 없이 만들어진 jar 파일이 의존성을 포함한 실행 가능한 jar 파일이다. 이제 jar 파일을 실행해보겠다.

➜  target ls -al
total 616
drwxr-xr-x  8 mhkim  staff     256 Mar 16 11:56 .
drwxr-xr-x  8 mhkim  staff     256 Mar 16 11:55 ..
drwxr-xr-x  3 mhkim  staff      96 Mar 16 11:56 classes
drwxr-xr-x  3 mhkim  staff      96 Mar 16 11:56 generated-sources
drwxr-xr-x  3 mhkim  staff      96 Mar 16 11:55 maven-archiver
drwxr-xr-x  3 mhkim  staff      96 Mar 16 11:55 maven-status
-rw-r--r--  1 mhkim  staff    2431 Mar 16 11:55 original-shadedtest-1.0-SNAPSHOT.jar
-rw-r--r--  1 mhkim  staff  310490 Mar 16 11:55 shadedtest-1.0-SNAPSHOT.jar
➜  target java -jar ./shadedtest-1.0-SNAPSHOT.jar 
Hello Maven!!
He...
➜  target 

 

기타

tar -tvf 명령어를 실행해 보면 해당 jar 구성 파일을 확인할 수 있다. 해당 명령어로 2개의 jar 파일을 실행해 보면 차이점을 분명하게 확인할 수 있다.

➜  target tar -tvf ./original-shadedtest-1.0-SNAPSHOT.jar 
drwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/
-rwxrwxrwx  0 0      0         131 Mar 16 11:55 META-INF/MANIFEST.MF
drwxrwxrwx  0 0      0           0 Mar 16 11:55 info/
drwxrwxrwx  0 0      0           0 Mar 16 11:55 info/m2sj/
-rwxrwxrwx  0 0      0         715 Mar 16 11:55 info/m2sj/M2sjMain.class
drwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/maven/
drwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/maven/org.example/
drwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/maven/org.example/shadedtest/
-rwxrwxrwx  0 0      0        1656 Mar 16 11:46 META-INF/maven/org.example/shadedtest/pom.xml
-rwxrwxrwx  0 0      0         113 Mar 16 11:55 META-INF/maven/org.example/shadedtest/pom.properties
➜  target tar -tvf ./shadedtest-1.0-SNAPSHOT.jar 
-rwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/MANIFEST.MF
drwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/
drwxrwxrwx  0 0      0           0 Mar 16 11:55 info/
drwxrwxrwx  0 0      0           0 Mar 16 11:55 info/m2sj/
-rwxrwxrwx  0 0      0           0 Mar 16 11:55 info/m2sj/M2sjMain.class
drwxrwxrwx  0 0      0           0 Mar 16 11:46 META-INF/maven/
drwxrwxrwx  0 0      0           0 Mar 16 11:46 META-INF/maven/org.example/
drwxrwxrwx  0 0      0           0 Mar 16 11:46 META-INF/maven/org.example/shadedtest/
-rwxrwxrwx  0 0      0           0 Mar 16 11:46 META-INF/maven/org.example/shadedtest/pom.xml
-rwxrwxrwx  0 0      0           0 Mar 16 11:55 META-INF/maven/org.example/shadedtest/pom.properties
drwxrwxrwx  0 0      0           0 Jul 13  2011 org/
drwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/
drwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/
drwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/
drwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/BackgroundInitializer$InitializationTask.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/ConstantInitializer.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/BasicThreadFactory.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/ConcurrentUtils.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/BasicThreadFactory$Builder.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/MultiBackgroundInitializer$1.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/CallableBackgroundInitializer.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/MultiBackgroundInitializer.class
-rwxrwxrwx  0 0      0           0 Jul 13  2011 org/apache/commons/lang3/concurrent/BasicThreadFactory$1.class
.
.
.
생략

 

References

더 많은 정보와 전체 소스 코드는 아래 링크에서 확인할 수 있다.

 

'Web Development' 카테고리의 다른 글

Shiro JdbcRealm(Postgresql)  (0) 2020.03.20
OSGI for Java Bundle Programing  (0) 2020.03.16
Multiple Java Version (Mac)  (0) 2020.02.24
multiple java version in ubuntu  (0) 2020.02.20
jenkins(ubuntu) + github + Startup #3  (0) 2020.02.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크