As widely reported (even enthusiastically by people other than Sun themselves), Java 1.5 (otherwise known as Tiger, otherwise known as 5.0) has generics. This is done by erasure originally for reasons of backwards compatibility. The idea was that Sun wanted to be able to compile source code with generics in it and run the generated bytecode on old JVMs. However, apparently late in the day, Sun decided not to, citing reasons of missing
Exception classes which is a fairly surmountable problem.
So, if you have any Java source file and compile it with
javac from the Java 1.5 SDK, the resulting
.class files blow up JVMs which don’t support Java 1.5.
-target flags so you can do
javac -source 1.5 -target 1.4 to try to get it to compile code suitable for 1.4 JVMs.
javac blows up saying that
source release 1.5 requires target release 1.5.
So, I created a very simple HelloWorld style program which didn’t use generics and compiled it twice: firstly with
-source 1.4 -target 1.4 and then with
-source 1.5 -target 1.5. The resulting
.class file has 1 byte difference between the two versions (in fact, just 1 bit difference). So, I then wrote some code that uses generics, compiled with
-source 1.5 -target 1.5, checked that it blew up if run on a 1.4 JVM and then edited this 1 byte in the class file. The change worked and as a result I could run the code with generics on a 1.4 JVM.
I then made use of Java libraries that have been genericifiedized, the most obvious example being the Collections API. I made the same hack and sure enough, it worked.
The danger is of course that you write code which uses APIs which were only introduced in Java 1.5 or worse, APIs who’s behaviour has changed between 1.4 and 1.5. Using
javac from the 1.5 SDK will compile against the 1.5 libraries. When you run it in a 1.4 JVM, it’ll be run against the 1.4 libraries. So, you could try to change the libraries that
javac compiles against, or you could change the libraries that
java runs against — you could make the 1.4 JVM use the 1.5 libraries. For that to happen you would have to unpack all of the Jars in the 1.5 JRE, make the hack on every class, reassemble, point the 1.4 JVM at these hacked libraries and then hope that it all works.
Of course, I’m not sure that you would want to run with the 1.4 JVM when the 1.5 JVM is available unless there was specific behaviour that you wanted. If the cost of validating your products against a 1.5 JVM was exhorbitant then you could continue to use a 1.4 JVM but tell your developers to start using generics, hack up a 1.5
javac coupled with the 1.4 libraries and a hack to change this one magic byte as a development environment and get generics at no extra cost.
Oh and the magic byte? Well, look at the
.class files in a hex mode (hexl-mode in emacs works well here). The first 4 bytes are
ca fe ba be. The next three bytes are all zeros. Then the next byte is
0) for 1.4 and
1) for 1.5.