We have a Java project that we wish to distribute to users. It does not use any Java features beyond Java 1.5, so we wish it to run on Java 1.5 and above.
At this point, you might rightfully note that Java 1.6 is the oldest available currently, so why target Java 1.5? However, that does not change the generic nature of the question of cross-compiling for older versions.
So, the way one usually starts cross-compilation attempts is by specifying -source 1.5
and -target 1.5
options to javac
, at which point one gets a famous warning about -bootclasspath
not being set:
$ javac -source 1.5 -target 1.5 Test.java
warning: [options] bootstrap class path not set in conjunction with -source 1.5
1 warning
Now, according to Oracle blog post, as well as official documentation, the correct practice for cross-compilation is to:
To use javac from JDK N to cross-compiler to an older platform version, the correct practice is to:
- Use the older -source setting.
- Set the bootclasspath to compile against the rt.jar (or equivalent) for the older platform.
If the second step is not taken, javac will dutifully use the old language rules combined with new libraries, which can result in class files that do not work on the older platform since references to non-existent methods can get included.
For instance, quoting official documentation:
% javac -source 1.6 -target 1.6 -bootclasspath jdk1.6.0/lib/rt.jar \
-extdirs "" OldCode.java
This is great and has been answered many times before both on Stack Overflow and the rest of the Internet.
However, none of the resources we have found seem to indicate where to actually find the rt.jar
for older versions of Java. As an example, JDK 1.7 does not ship with rt.jar
except its own:
$ find jdk-1.7.0_45 -name rt.jar
jdk-1.7.0_45/jre/lib/rt.jar
That makes one think that in order to obtain rt.jar
for Java 1.6, for instance, one needs to download JDK 1.6. But then two questions arise:
So, how do we actually specify -bootclasspath
option to use this cross-compilation feature?
You can use the -jo compiler command line option in order to specify options to be passed to the Java compiler such as: "-source" and "-target". In order to check the version number in a . class file you can use the javap utility that is distributed with the JDK.
By default, the bootstrap classpath consists of the "rt. jar" file and some other important JAR files that are supplied by the JRE installation. These provide all of the classes in the standard Java SE class library, along with various "internal" implementation classes.
Yes, it is possible for target to be greater than source. That is, we can write code using strictly java 8 syntax, and (using a java 11 or later compiler) compile it to java 11 bytecode.
The javac command reads class and interface definitions, written in the Java programming language, and compiles them into bytecode class files. The javac command can also process annotations in Java source files and classes.
The rt.jar is included with the JRE. You will be able to perform the cross compilation if you have, say, JDK 1.6 and JRE 1.5.
Using your JDK 1.6:
$ javac -source 1.5 -target 1.5 -bootclasspath jre1.5.0/lib/rt.jar Test.java
The advantage here is that the JRE can be as little as 1/3 the size of a full JDK. You can often remove old JDK versions without removing old JRE versions.
If you need to get hold of an old JRE, they can be found following links on the Java Archive page http://www.oracle.com/technetwork/java/javase/archive-139210.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With