top bar

글 목록

2015년 11월 22일 일요일

[JAVA] Executable(or Runnable) JAR 파일 생성

개요


JAR(Java Archive, 자바 아카이브)는 소프트웨어에서 수많은 자바 클래스 파일과 연관 메타데이터, 리소스(텍스트, 그림 등)을 하나의 파일로 모아서 자바 플랫폼에 응용 어플리케이션이나 라이브러리를 배포하기 위한 패키지 파일 포맷이다.(출처: 위키 백과)

하지만 'main' 메소드를 구동하여 하나의 자바 어플리케이션 으로서 동작하게 하려면 특별한 설정이 필요하다. 이제 자바 'Manifest' 파일을 통해 'Runnable JAR' 파일을 생성하는 법을 알아 보고자 한다.


JAR 파일 생성


먼저 아래와 같은 기본적인 'HelloWorld' 클래스를 컴파일하고, 'jar' 파일을 생성해보자.
package test;

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}
컴파일한다
> javac -d . HelloWorld.java
시험삼아 구동해보자
> java test.HelloWorld
Hello world!
이제 jar 파일을 생성해본다. 이는 jdk bin 폴더 아래에 있는 'jar' 실행파일을 사용한다.
환경변수를 설정했다면 어디서든 'jar' 명령어를 사용 할 수 있다.
> jar -cf helloworld.jar test\*.class
참고로 아무것도 없이 'jar' 명령어만 치면 usage 목록이 쫙 나오고 각 옵션에 대한 설명도 나온다. 일단 위에서는 'c'와 'f' 옵션을 사용했는데, 직관적으로 보이겠지만 'c'는 새로운 아카이브 파일을 생성하는 것이고 'f'는 파일의 이름을 지정하는 것이다.

'-cf' 옵션뒤에 첫번째 파라미터는 jar파일의 이름, 둘째는 아카이빙될 .class 파일을 입력하는데, 여기서는 와일드카드(*)를 사용하였다.

이제 생성된 jar파일을 구동해볼까나?
> java -jar helloworld.jar
helloworld.jar에 기본 Manifest 속성이 없습니다.
이것이 필자가 이 글을 쓰고 있는 이유이다. 실무에서도 실행가능한 jar파일을 생성하지 못하여 위와 같은 메시지를 자주 접했었다. 이제 JAVA Manifest 파일을 통해서 실행가능한 jar파일을 생성해 보도록 하자.


JAVA Manifest 파일


JAVA Manifest 파일은 해당 자바 어플리케이션의 정보 즉, 일종의 메타정보를 담고 있는 파일이다. 아래에 가면 아주 자세한 Tutorial을 볼 수 있다.

https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

일단 jar 명령어로 jar파일을 생성할때, META-INF/MANIFEST.MF 파일이 자동으로 jar 패키지에 포함된다. 일단 위에서 생성된 'helloworld.jar' 파일을 jar 명령어로 압축을 풀어보자.
> jar -xvf helloworld.jar
생성됨: META-INF/
증가됨: META-INF/MANIFEST.MF
증가됨: test/HelloWorld.class
위에서 볼 수 있는 것처럼 MANIFEST.MF 파일이 포함되어 패키지가 구성되어 있다는 것을 알 수 있다. 자동적으로 생성되는 default MANIFEST.MF 파일의 내용은 아래와 같다.
> type META-INF\MANIFEST.MF
Manifest-Version: 1.0
Created-By: 1.7.0_67 (Oracle Corporation)
Manifest-Version과 파일을 생성한 주체가 표시 되어 있다. 위 예에서 볼수 있듯이 Manifest파일의 기본 포맷은 'key: value' 의 포맷이다.

자동적으로 Manifest 파일이 생성되어 패키지에 포함되어 있는데 왜 기본 Manifest 속성이 없습니다. 라는 오류 메시지가 노출된 것일까?


Entry Point 설정


기본적으로 JAVA 어플리케이션은 'main' 메소드로 구동되는건 알 것이다. 이를 'Entry Point' 라고도 하나보다. 이제 Manifest 파일에 'Entry Point'를 설정해보자.

아래와 같은 내용으로 'Manifest.txt'를 생성한다
Main-Class: test.HelloWorld
그냥 한줄만 입력했다. 말그대로 'main' 메소드를 구동시키는 'Main-Class'를 지정한 것이다. 간단하지 않은가? 이 Manifest.txt 파일을 이용해 다시한번 jar 파일을 생성해보자.
> jar -cfm helloworld.jar Manifest.txt test\*.class
최초 '-cf' 옵션만을 사용했었는데, 여기다 'm' 옵션이 추가되었다. 말그대로 Manifest 파일을 포함해 jar파일을 생성하겠다는 의미 이다.

이제 다시 'helloworld.jar'파일을 구동해보자.
> java -jar helloworld.jar
Hello world!
이제 잘 구동된다.

하지만 Manifest 파일을 이용하지 않고도 Main-Class 지정, 즉 Entry Point를 설정하는 더 간단한 방법이 있다.
> jar -cfe helloworld.jar test.HelloWorld test\*.class
바로 위처럼 'e' 옵션을 사용하는 것이다. '-cfe' 옵션뒤에 jar 파일 이름, Main클래스 경로, jar 아카이빙될 클래스파일 경로를 지정한다. 위와 같이 하면 Manifest 파일을 사용하지 않고 'main' 메소드를 구동할 Main클래스를 지정할 수 있다!


Eclipse에서 'Runnable JAR' 생성하기


1) Project 우클릭 > Export






















2) JAVA > Runnable JAR file






















3) Launch Configuration 및 Export destination 선택 후 Finish























이때, Launch configuration은 해당 main 클래스의 실행 이력이 있다면 자동으로
생성되어 있을 것이다. 만약 select box에 아무것도 안뜬다면 이클립스의 'Run configuration' 에서 새로운 실행 설정을 추가해야 한다.


마치며..


이 topic에 대해서 포스팅을 하려고 마음먹었던 이유는 저 위의 기본 Manifest 속성이 없습니다. 와 같은 빌어먹을 오류 때문이었다. 보통 jar 파일 패키지 산출은 eclipse나 maven과 같은 빌드 도구가 알아서 해주다 보니, 저런 오류를 만나면 어디서부터 문제를 해결해야 할지 답답했다.

정말 요즘은 IDE나 갖가지 개발업무를 도와주는 Tool들 덕분에 개발자들이 해야할 일이 많이 줄어든건 사실이지만, 자신이 하는 개발업무 자체에 대한 깊이는 그만큼 얕아진것 같다. 물론 여기서 다루지 않은 JAVA 'Manifest' 파일의 스펙은 무척 다양하다.

하지만 오늘 포스팅을 하면서, 기본적으로 JAVA 어플리케이션이 어떻게 Main 메소드가 있는 클래스를 찾아서 프로그램을 실행 시키는지 이해 할 수 있었던 것 같다.

댓글 5개: