Get java compiler version of a class file using xxd

293 views Asked by At

I need to get the version of java that was used to compile a class file from a linux machine that doesn't have java. I have learned from a comment on this post that this is possible using xxd.

Alternatively, if you open the class file in a hex editor you can look at bytes 7 and 8. The number will map to the numbers given in the above answer. E.g. 00 2E -> JDK 1.2 = 46 (0x2E hex). Useful if you don't have access to javap.

However, it isn't clear to me how the output is interpreted. The first few lines of xxd displays this:

00000000: cafe babe 0000 0031 009b 0500 0000 0000  .......1........
00000010: 0027 1005 0000 0000 0000 4e20 0500 0000  .'........N ....

How can I read this? There is a nice wiki page here, but it doesn't seem to follow my understanding of bytes. I believe ASCII is supposed to be one byte per character, which would mean that "cafe babe" is 8 bytes. The wiki page shows it to be 4 bytes. Assuming that pattern is followed, then that would be that byte five is "00", six is "00", seven is "00", and eight is "31". If this is correct, then by converting this to decimal, the minor version is (0x00 0x00) = 0, and the major version is (0x00 0x31) = 49. The chart linked in the post I linked shows this to be Java 5. Is this correct?

2

There are 2 answers

0
stdunbar On BEST ANSWER

The simplest way is with the file command:

$ file FileSha256.class 
FileSha256.class: compiled Java class data, version 55.0 (Java SE 11)

This is from an Ubuntu 22.04 system - I haven't tested on others. While I do have Java installed an strace shows that it is never accessed. Does it have to be xxd?

0
that other guy On

The xxd output format is:

00000000: cafe babe 0000 0031 009b 0500 0000 0000  .......1........
00000010: 0027 1005 0000 0000 0000 4e20 0500 0000  .'........N ....
|------|  |-------------------------------------|  |--------------|
address   16bit hex words                          ASCII if printable

Since each word is 16 bits / 2 bytes, represented as 4 hex digits, the 7th and 8th byte is the fourth word, 0031, which in decimal is 49, corresponding to Java 5.0.

(cafe babe is not ASCII but instead a hexadecimal joke, using the hex digits A-F to spell out english words. This is like how decimal 3735928559 happens to spell out 0xDEADBEEF in hexadecimal)

Note that this will tell you the bytecode version the compiler targeted, not necessarily which compiler was used. You can't tell whether the class was compiled by JDK 5.0 or by JDK-12 with -target 5.