※ 참고

OS : CentOS Linux release 7.4.1708 (Core)

JAVA : openjdk version "1.8.0_151"


리눅스에서 Java를 사용해서 프로그램 하나를 작성했다.

컴파일은 문제 없이 되었고, 더욱 편하게 컴파일 하기 위해 Makefile을 작성했다. 

그리고 이 프로그램은 백그라운드에서 돌아야하기 때문에 commons-daemon 이라는 라이브러리를 사용해서 데몬으로 만들었다.



[그림] 내가 생성한 프로젝트 폴더 구조


- 프로젝트 컴파일 및 실행과정


# make 명령어를 주면 /src 폴더에 있는 .java 파일들을 컴파일해서 나온 .class 파일들을 /bin 폴더 안에 넣는다.

# jar -uvf ... 명령어를 주면 .class 파일들을 .jar 파일로 압축한다. (이후 -uvf 명령어로 .jar 파일을 업데이트한다)

# ./TestProject.bin start 명령어를 주면 스크립트 파일이 프로젝트를 실행한다.


이 상황에서 데몬 실행중에 'ClassNotFoundException' 이라는 에러가 발생했다.


- 에러 발생 상황


# make clean을 실행하고(/bin 폴더의 *.class, /out 폴더의 daemon.* 삭제됨)

# cd bin

# rm TestProject.jar

# cd ..

# jar -cvf bin/TestProject.jar bin/*.class

# ./TestProject.bin start

...

...ClassNotFoundException

...


제대로 생성하지 않았다?

다음의 경우에는 에러가 발생하지 않았다.


- 실행이 잘됨


# make clean을 실행하고(/bin 폴더의 *.class, /out 폴더의 daemon.* 삭제됨)

# cd bin

# rm TestProject.jar

# jar -cvf TestProject.jar *.class

# cd ..

# ./TestProject.bin start

...

실행 잘됨

...


차이점은? jar 생성할 때 현재 디렉토리가 어딘지에 따른 차이...

혹시 상대 경로로 실행해서 그런건가?

- 절대경로로 바꿔봄


...

# jar -cvf /root/test/bin/TestProject.jar /root/test/bin/*.class

# ./TestProject.bin start

...

...ClassNotFoundException

...

에러 발생


jar를 -cvf 옵션을 줘서 만드는게 아니라 -uvf 옵션을 줘서 업데이트를 한다면? 역시나 같은 문제 발생.

만약 실행이 잘된 상황에서 소스코드에 Print문을 수정한 후, 소스코드 컴파일, jar 업데이트, 스크립트 실행 순으로 했을 때 결과 값은 

수정 전의 프로젝트가 실행이 된다.


결론, jar 파일을 생성이나 업데이트할 땐, Class 파일이 존재하는 폴더에서 해야한다는 것

1. jar -uvf TestProject.jar bin/*.class (X)

2. jar -uvf ../TestProject.jar *.class (O)

3. jar -uvf TestProject.jar *.class(O)


뭐 때문에 이런거지? 버그인가?