It is easy to have more than on JDK or JRE version(in particular JRE -- because of browser plugin downloads!) in the same machine. If you compile your Java source(s) with a JDK version and run the same with with an earlier JDK/JRE version, you could get an error that looks like this:
Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file
Now, how do I know what is the version of a .class file and what version of JDK I need to run the same? The section 4.1 of VM spec. edition 2 explains the "header" structure of every .class file:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
The magic of a .class file is 0xCAFEBABE. The following class takes a class file as input and prints the major, minor version of it and also prints minium JDK/JRE required to run the given class.
File: Version.java
import java.io.*;
public class Version {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: java version <.class file>");
System.exit(1);
}
if (! new File(args[0]).exists()) {
System.err.println(args[0] + " does not exist!");
System.exit(2);
}
DataInputStream dis = new DataInputStream(
new FileInputStream(args[0]));
int magic = dis.readInt();
if (magic != 0xcafebabe) {
System.err.println(args[0] + " is not a .class file");
System.exit(3);
}
int minor = dis.readShort();
int major = dis.readShort();
System.out.println("class file version is " + major + "." + minor);
String version = null;
if (major < 48) {
version = "1.3.1";
} else if (major == 48) {
version = "1.4.2";
} else if (major == 49) {
version = "1.5";
} else if (major == 50) {
version = "6";
} else {
version = "7";
}
System.out.println("You need to use JDK " + version + " or above");
}
}
For example, after compiling the above class with JDK 1.5 and running it against itself prints the following:
java -cp . Version Version.class
class file version is 49.0
You need to use JDK 1.5 or above
John O'Conner has written a nice article on scripting for the Java platform. This is a well written article with sample code. One minor thing: there was a change in javax.script.Invocable interface after the article was written/reviewed. You may have to change the downloaded code -- if you are working with Mustang build 91 or above.