Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

What version is your Java code?

Write and compile code targeting different Java versions

  • Print
  • Feedback

Page 2 of 5

Although the last code example was somewhat artificial, it served to illustrate a point. Other reasons to use a recent J2SDK version include wanting to benefit from javadoc and other tool improvements.

Finally, cross-compilation is quite a way of life in embedded Java development and Java game development.

Hello class puzzle explained

The Hello example that started this article is an example of incorrect cross-compilation. J2SE 1.4 added a new method to the StringBuffer API: append(StringBuffer). When javac decides how to translate greeting.append (who) into byte code, it looks up the StringBuffer class definition in the bootstrap classpath and selects this new method instead of append(Object). Even though the source code is fully Java 1.0 compatible, the resulting byte code requires a J2SE 1.4 runtime.

Note how easy it is to make this mistake. There are no compilation warnings, and the error is detectable at runtime only. The correct way to use javac from J2SE 1.4 to generate a Java 1.1-compatible Hello class is:

>...\jdk1.4.1\bin\javac
    -target 1.1
    -bootclasspath ...\jdk1.1.8\lib\classes.zip
    Hello.java


The correct javac incantation contains two new options. Let's examine what they do and why they are necessary.

Every Java class has a version stamp

You may not be aware of it, but every .class file you generate contains a version stamp: two unsigned short integers starting at byte offset 4, right after the 0xCAFEBABE magic number. They are the major/minor version numbers of the class format (see the Class File Format Specification), and they have utility besides just being extension points for this format definition. Every version of the Java platform specifies a range of supported versions. Here is the table of supported ranges at this time of writing (my version of this table differs from data in Sun's docs slightly—I chose to remove some range values only relevant to extremely old (pre-1.0.2) versions of Sun's compiler):

Java 1.1 platform: 45.3-45.65535
Java 1.2 platform: 45.3-46.0
Java 1.3 platform: 45.3-47.0
Java 1.4 platform: 45.3-48.0


A compliant JVM will refuse to load a class if the class's version stamp is outside of the JVM's support range. Note from the previous table that later JVMs always support the entire version range from the previous version level and also extend it.

What does this mean to you as a Java developer? Given the ability to control this version stamp during compilation, you can enforce the minimum Java runtime version required by your application. This is precisely what the -target compiler option does. Here is a list of version stamps emitted by javac compilers from various JDKs/J2SDKs by default (observe that J2SDK 1.4 is the first J2SDK where javac changes its default target from 1.1 to 1.2):

JDK 1.1: 45.3
J2SDK 1.2: 45.3
J2SDK 1.3: 45.3
J2SDK 1.4: 46.0


And here is the effect of specifying various -targets:

-target 1.1: 45.3
-target 1.2: 46.0
-target 1.3: 47.0
-target 1.4: 48.0


As an example, the following uses the URL.getPath() method added in J2SE 1.3:

  • Print
  • Feedback

Resources