You cannot specify the minor number yourself during the compilation.
The major and minor number does not indicate the version of the JDK used to compile. They indicate the version of the class file format. Have a look at this SO answer.
The class file version also specify the version of JRE able to execute this class file. For example: if the major.minor version is 0x30.0x00 you need at least a JRE 1.4 to execute this class file. Which not in all cases mean a previous JRE couldn't understand the byte code. As soon you use a Java language feature/runtime class which did not exist in a previous Java version this isn't true anymore.
A simple example
public class Scratch {
public static void main(String[] args) {
System.out.println("foobar");
}
}
This simple class can be compiled with a different then the default class file version of your JDK
Following would compile it for the version 1.4
javac -source 1.4 -target 1.4 Scratch
The generated bytecode would in this simple example still be the same. The lowest possible class file version for this simple example would be 2D.E (compile it with javac -target 1.1 -source 1.2 Scratch.java). And then a JRE 1.1 (verified with JRE 1.1.8) could run it.
To check the version you could use this snippet
import java.io.DataInputStream;
import java.io.FileInputStream;
public class ClassFileVersion {
// add exception handling, left out only for the example
public static void main(String[] args) throws Exception {
String filename = args[0];
try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
int magic = in.readInt();
if (magic != 0xcafebabe) {
System.out.println(filename + " looks not like a Java class file.");
}
int minor = in.readUnsignedShort();
int major = in.readUnsignedShort();
System.out.printf("majaor.minor: %X.%X hex %d.%d dec%n", major, minor, major, minor);
}
}
}
edit
Here a small snippet to demonstrate the impact.
- compile the above
Scratch.java
with your current JDK
run the class file minor version of the Scratch.class
Path path = Paths.get("Scratch.class");
byte[] bytes = Files.readAllBytes(path);
bytes[5] = 1; // it was zero before
Files.write(path, bytes, StandardOpenOption.TRUNCATE_EXISTING)
run the changed class file java Scratch
the execution will fail (error message might be differ in the wording, depending on your used JRE)
java.lang.UnsupportedClassVersionError: Scratch has been compiled by a more recent
version of the Java Runtime (class file version 52.1), this version of the Java Runtime
only recognizes class file versions up to 52.0
If you compile the source for a lower major version (the -target option) an previous JRE could execute the bytecode (see the limitations mentioned earlier).
Assume you run this with JDK 8 javac -target 1.4 -source 1.4 Scratch.java
. There are different things happen by the javac
. First it checks if Scratch.java
only use language features which were available in Java 1.4. Second the resulting Scratch.class
get a major.minor class file version which was used in Java 1.4 (30.0 hex). Then you could run this class with the JRE 1.4 as java Scratch
.