The JVM versions your Java classes will run on is often determined by how you compile them. Failure to take care with your classes and dependencies can lead to an UnsupportedClassVersionError. This post demonstrates how to check your class files.
The class file format
Information on the Java binary format can be found in The Java Virtual Machine Specification. The ClassFile Structure defines the format and specifies that the version will be contained in the first eight bytes.
ClassFile { u4 magic; u2 minor_version; u2 major_version; ...remainder elided... }
This can be seen by doing a hex dump of a .class
file.
magic | minor_version | major_version | |||||
---|---|---|---|---|---|---|---|
CA | FE | BA | BE | 00 | 00 | 00 | 32 |
The first eight bytes of a class compiled with Java 1.6 |
The class file in the table has a major version of 0x32
and a minor version of 0x0
. The decimal value (50.0)
matches the version stored in the JVM's system
properties:
System.out.println(System |
Targeting old Java versions with newer compilers
Java compilers let you target older class versions to run on older VMs.
public class Java {}
The above Java file can be compiled to various class file versions using the Java 6 javac JDK compiler:
javac -source 1.3 -target 1.1 Java.java javac -source 1.3 -target 1.2 Java.java javac -source 1.3 -target 1.3 Java.java javac -source 1.3 -target 1.4 Java.java javac -source 1.3 -target 1.5 Java.java javac -source 1.3 -target 1.6 Java.java
Note that the class versions are different to the Java libraries that are available in older JVMs. If you target an older JVM, you need to restrict your API calls to the ones available in that version.
Reading the Java versions
The following ClassFile versions are supported by various JVMs:
Maximum Class File Version | Java Version | Source |
---|---|---|
45.3 | 1.0.2 | documentation |
45.65535 | 1.1.X | documentation |
46.0 | 1.2 | documentation |
47.0 | 1.3 | experimentation |
48.0 | 1.4 | experimentation |
49.0 | 5 | experimentation |
50.0 | 6 | experimentation |
I can't be 100% certain about the values in the table determined by experimentation - if you can find canonical information from Sun, please drop a link into a comment.
This code reads the start of a class binary file from a stream to find the major and minor version numbers:
DataInputStream data = new DataInputStream(in); |
Sample Code
All the sources are available in a public Subversion repository.
Repository:
http://illegalargumentexception.googlecode.com/svn/trunk/code/java/
License: MIT
Project: JavaClassVersionLib
You can download a binary version here: javaClassVersionLib_1.1.zip. (download updated 26 Nov '09)
Joseph D. Darcy has a post on class file version numbers.
ReplyDelete