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
May 23, 2003
How do you support different Java versions in the same application?
To pique your interest from the start, let me begin with a short puzzle. Look at the following small program and answer the
question: Which Java runtime versions are compatible with it?
public class Hello
{
public static void main (String [] args)
{
StringBuffer greeting = new StringBuffer ("hello, ");
StringBuffer who = new StringBuffer (args [0]).append ("!");
greeting.append (who);
System.out.println (greeting);
}
} // End of class
At first the question seems rather trivial. So little code is involved in the Hello class, and whatever there is uses only functionality dating back to Java 1.0. So the class should run in just about any JVM
with no problems, right?
Don't be so sure. Compile it using javac from Java 2 Platform, Standard Edition (J2SE) 1.4.1 and run it in an earlier version of the Java Runtime Environment (JRE):
>...\jdk1.4.1\bin\javac Hello.java
>...\jdk1.3.1\bin\java Hello world
Exception in thread "main" java.lang.NoSuchMethodError
at Hello.main(Hello.java:20)
Instead of the expected "hello, world!," this code throws a runtime error even though the source is 100 percent Java 1.0 compatible! And the error isn't exactly what you might expect either: instead of a class version mismatch, it somehow complains about a missing method. Puzzled? If so, you will find the full explanation later in this article. First, let's broaden the discussion.
Java is quite platform-independent and mostly upwards compatible, so it is common to compile a piece of code using a given J2SE version and expect it to work in later JVM versions. (Java syntax changes usually occur without any substantial changes to the byte code instruction set.) The question in this situation is: Can you establish some kind of base Java version supported by your compiled application, or is the default compiler behavior acceptable? I will explain my recommendation later.
Another fairly common situation is to use a higher versioned compiler than the intended deployment platform. In this case, you do not use any recently added APIs, but merely want to benefit from tool improvements. Look at this code snippet and try to guess what it should do at runtime:
public class ThreadSurprise
{
public static void main (String [] args)
throws Exception
{
Thread [] threads = new Thread [0];
threads [-1].sleep (1); // Should this throw?
}
} // End of class
Should this code throw an ArrayIndexOutOfBoundsException or not? If you compile ThreadSurprise using different Sun Microsystems JDK/J2SDK (Java 2 Platform, Standard Development Kit) versions, behavior will not be consistent:
The subtle point here is that Thread.sleep() is a static method and doesn't need a Thread instance at all. Still, the Java Language Specification requires the compiler to not only infer the target class from the
left-hand expression of threads [-1].sleep (1);, but also evaluate the expression itself (and discard such an evaluation's result). Is referencing index -1 of the threads array part of such an evaluation? The wording in the Java Language Specification is somewhat vague. The summary of changes for J2SE 1.4 implies that the ambiguity was finally resolved in favor of evaluating the left-hand expression fully. Great!
Since the J2SE 1.4 compiler seems like the best choice, I want to use it for all my Java programming even if my target runtime
platform is an earlier version, just to benefit from such fixes and improvements. (Note that at the time of writing not all
application servers are certified on the J2SE 1.4 platform.)