Alex headshot

AlBlue’s Blog

Macs, Modularity and More

Compiling Java Generics with 1.4 compatibility

Java 2010 Howto Eclipse

If you're using Eclipse to compile Java code with generics, but need to maintain Java 1.4 compatibility, then there's a hidden option you can enable to compile Java 1.5 source code and produce 1.4 (version 48) bytecode.

Normally, you switch between compliance levels using the -source and -target command line switches for the Java compiler, or in Eclipse's case, by right-clicking on a project and going to the Java Compiler and changing the 'source' and '.class file compatibility' elements. However, you can't select the 1.4 generated class file compatibility (or the -target flag) with the 1.5 source (or -source flag) option, as you get an error saying that it's not a supported combination.

There is a less well known flag you can specify to the command line compiler called -target jsr14, which is equivalent to the 1.4 option – except that it permits a source code format of 1.5, thus permitting generics to be used. This was introduced in the transition to generics, mainly for testing purposes, in the run up to Java 1.5's release. However, it's still accepted today by Java 6 compilers.

Unfortunately, you can't select JSR14 from the drop-down list in Eclipse – but you can enable it anyway. Eclipse writes its compiler preferences into a file called .settings/org.eclipse.jdt.core.prefs. (This file gets generated when you've made a change to the Compiler Settings preferences pane in Eclipse; if it's not there, you can just change the compiler settings to 1.5 to get it to be generated.) Once it's there you can change the targetPlatform setting to jsr14. Alternatively you can just paste the following line in to the file:

org.eclipse.jdt.core.compiler.codegen.targetPlatform=jsr14

Note that whilst generics are supported with this method, other Java 1.5 features, like Enums, are not supported. That's because Enums are compile-time translated to subtypes of java.lang.Enum, which of course doesn't exist in the Java 1.4 runtime. Incidentally, the jsr14 flag refers to JSR 14, which was the JSR to add generics to the Java language.

This feature is used as part of the new OSGi 4.3 features to generify the existing libraries whilst maintaining binary compatibility with older VMs, which I wrote more about for InfoQ recently. This largely forgotten feature is still supported by Sun/Oracle VMs as well as others like GCJ and IBM.

Note that the same technique can be used to generate code with automated build scripts such as Maven or Ant:

<!-- Maven -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <source>1.5</source>
        <target>jsr14</target>
    </configuration>
</plugin>

<!-- Ant -->
<javac source="1.5" target="jsr14"/>