Class 파일 JDK 버전 확인
Java 프로그램을 개발하다보면 어떤 JDK로 빌드되었는지 확인할 필요가 있다. 다행히도 컴파일된 Class파일이나 컴파일된 Jar파일 안에는 컴파일 할 때 사용했던 JDK 버전에 대한 정보가 포함되어 있기 때문에 확인할 수 있는 방법이 있다. 특히, 다른 사람이 만든 외부 라이브러리를 가져와서 자신의 프로젝트에 포함해서 사용하는 경우에 자주 확인되는 것 같아서, 이번에 JDK를 확인할 수 있는 방법 세가지를 소개한다.
JDK를 확인하는 방법을 설명하기 전에, 아래 표 하나만 이해하고 넘어가보겠다. Class 파일 내부에는 컴파일된 JDK 버전이 포함되어 있지만, 이 정보를 확인하면 우리가 보통 사용하는 JDK 버전(ex, 1.8, 1.7)으로 표시된 것이 아니라, 10진수나 16진수로 확인할 수 있다. 따라서 이어서 소개하는 3가지 방법에서 확인된 값을 아래 표와 매칭해서 확인하는 것이 편할 것이다.
JDK | 10진수(Dec) | 16진수(Hex) |
..(생략) | .. | .. |
1.8 | 52 | 34 |
1.7 | 51 | 33 |
1.6 | 50 | 32 |
1.5 | 49 | 31 |
1.4 | 48 | 30 |
1.3 | 47 | 2F |
1.2 | 46 | 2E |
..(생략) | .. | .. |
방법1. javap 프로그램 사용
PC에 설치된 jdk에 포함되어 있는 javap 프로그램을 사용해서 확인할 수 있다. 현재 개발자가 PC에서 jdk를 어떻게 설정했냐에 따라 경로가 다를 것이므로, 각자 알아서 찾아서 javap를 실행하면 된다. 참고로, 대부분 jdk/bin이 이미 환경변수로 등록되어 있을 것이므로 command 하나를 열어서 바로 실행이 가능할 것이다.
// 사용 방법
$ javap -verbose [class file] | find /N "version"
// 예시
$ javap -verbose Sample.class | find /N "version"
출력 :
[6] minor version: 0
[7] major version: 52
위 [예시]처럼 실행하면, [출력] 형태처럼 값을 확인할 수 있을 것이다. 여기서 컴파일된 버전은 major version을 확인하면 된다. 위 Sample.class 파일은 52이므로 JDK 1.8로 컴파일되었다는 의미이다.
방법2. Hex 값으로 직접 확인
Hex 값을 읽을 수 있는 에디터(ex, UltraEdit, HxD)로 버전을 확인하려는 Class 파일을 실행시키면 아래처럼 Class 파일에 대한 Hex값이 보일 것이다. 이 값들을 해석하면 JDK 버전을 확인할 수 있다.
CA FE BA BE 00 00 00 [JDK version] 00 ...
CA FE BA BE 00 00 00 34 00 ...
Class 파일을 읽으면 앞에서부터 위와 같이 맨 앞에서부터의 값이 "CA FE BA BE 00 00"으로 시작하는 것을 볼 수 있고, 바로 이어지는 다음 1바이트값이 컴파일된 버전을 의미한다. 위 Sample.class 파일은 34인데 이 값은 16진수(Hex)값이므로 이를 10진수로 변경하면 52이다. 따라서 JDK 1.8로 컴파일되었다는 의미이다.
방법3. 직접 코딩해서 확인
사실 JDK버전을 확인하기 위해서는 위의 방법1과 방법2로 쉽게 확인할 수 있지만, 혹시 직접 구현중인 프로그램 내에 버전 체크로직을 삽입해야 하는 경우라면 아래처럼 확인해볼 수 있다.
public static void checkClassVersion(String filename) throws IOException {
DataInputStream in = new DataInputStream(new FileInputStream(filename));
int magic = in.readInt();
if(magic != 0xcafebabe) {
System.out.println(filename + " is not a valid class!");;
}
int minor = in.readUnsignedShort();
int major = in.readUnsignedShort();
System.out.println(filename);
System.out.println(major);
System.out.println(minor);
in.close();
}