Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
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
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.
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.
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: