본문 바로가기
Language/☕️Java

class파일로 컴파일 후, FTP를 통한 배포에서 발생한 문제. (UnsupportedClassVersionError )

by 발개발자 2021. 8. 14.
반응형

최근 특정 레거시 시스템에서 소스 수정이 필요했다. 

JEUS를 WAS로 사용하는 리눅스 서버였다.

배포형태는 Maven이나 gradle을 사용하여 war, jar형태로 압축하여 배포하는 형태가 아닌,

class파일로 배포하는 형태였다.

 

배포를 하기 전, 소스를 수정한 후 SAP와 인터페이스 테스트까지 모두 마친 후 Svn을 통해 형상관리까지 해놓은 후 배포를 기다리고 있었다.

현업사용자들이 모두 퇴근한 후, 배포를 시작했다.

먼저, 웹서버와 WAS를 모두 shut down 시킨 후 기존 class파일을 백업하였다.

그리고 수정한 java 소스코드를 class파일로 컴파일 한 후, FTP를 통하여 class파일을 배포하였다.

그리고 웹서버와 WAS를 모두 start시켰다.

서버도 정상적으로 start된 것을 확인한 후, 브라우저를 통해 접속하니 500 error페이지가 발생하였다.

 

간단한 작업이라, 금방 끝날 줄 알았는데 갑자기 에러가 발생하여 원인을 분석해보기로 했다.

JEUS와 Apache의 로그를 확인하였는데, 서버가 켜졌다는 로그이후 별다른 로그가 남지 않아 있었다.

 

먼저, 첫번째로 추론한 경우는 해당 시스템이 10년이 넘은 워낙 레거시한 시스템이기 때문에 기존에 배포된 class파일과 내가 수정하기 시작한 소스가 다를 경우였다. 해당 문제를 확인하기 위해, class파일 디컴파일러를 통해 소스를 비교해보기로 했다.

디컴파일러는 아래의 경로를 통해 jd-gui를 설치받아 확인하였다.

http://java-decompiler.github.io/#jd-gui-download

 

내가 수정한 클래스파일과 소스를 비교한 결과, 내가 수정한 부분 이외에는 버전이 일치한 것을 확인하였고 내가 수정한 부분은 테스트까지 모두 완료하였으니 이 경우는 일단 넘어가기로 하였다.

 

두번째로 추론한 경우는, class파일의 컴파일 버전이 다를 경우였다.

jdk는 하위버전에서 class파일로 컴파일하여 상위버전에선 구동은 가능하지만,

반대로 상위버전에 class파일로 컴파일하여 하위버전에서 구동시키는 건 부적합하다.

 

좀 더 자세히 알고 싶어서, 테스트로 같은 소스코드를 다른 버전의 jdk로 컴파일 하여 구동하였는데,

구동하는 서버의 jre보다 상위버전의 class파일에서는 UnsupportedClassVersionError 같은 오류가 발생되었다.

 

같은 소스코드라도, 최신 jdk에서 지원하는 클래스라던지 기능을 안써도 다른 컴파일 결과를 발생시킬 수 있다는건데,

현재까지 알아본 결과, 좀 더 상위의 jdk가 최적화를 위해 대상 바이트코드가 바뀔 수가 있다고 한다.

그래서 JVM이 class파일을 로드하는 과정에서 컴파일된 버전을 확인한 후 UnsupportedClassVersionError 에러를 발생시키지 않았나 싶다.

 

그렇다면 지금 상황도 이러한 경우인지 바로 확인하였다.

배포되는 해당 서버의 java 버전을 확인한 결과 1.6이었다.

 

명령어를 통해 기존 class파일들의 컴파일 버전을 확인하였다.

javap -verbose FileName | find "version"
class 파일들도 1.6버전에서 컴파일 되어있었다.

 

분명히 jdk를 작업하기전 1.6으로 셋팅해놓은 줄 알았는데,,,,,,,,,,,,,,,,,,,

이것저것 인터페이스 테스트를 하다보니 jdk1.7(x86)를 사용하고 다시 원복을 안시켜놨었다. (진짜.. 삽질의 연속)

 

JDK를 1.6으로 바꿔준 후, 다시 컴파일하였다. 컴파일 한 class파일을 다시 서버의 FTP로 전송하여 서버를 실행하니 정상적으로 오류가 해결되었다.

(아래 사진 처럼 굳이 JDK1.6이 아니더라도, 보다 상위버전에서 JDK Compilance를 1.6으로 바꿔줄 수 있다.) 

해당 레거시 시스템에서 maven이나 gradle같은 빌드 툴로 컴파일버전을 셋팅하여 형상관리하는 형태가아닌,

각각의 java파일을 컴파일 후 빌드하는 방식을 사용하고 있다보니, 버전 셋팅에 대한 이슈도 이렇게 발생할 수 있겠다 싶었다.

(maven 컴파일버전을 셋팅한 예)

 

결국, UnsupportedClassVersionError 에러는 실행되는 서버에서 java버전을 확인한 후, 해당 버전에 맞는 jdk로 다시 컴파일해주면 해결 된다.

반응형

댓글