Monday, December 04, 2006

Java Compiler Woes

To cut a long story short, I lost a couple days of effort to discover that you should always use the version of the Java compiler that matches your production environment. Take for example this little piece of Java code:

import java.math.BigDecimal;

public class BigDecimalTest {
public static void main(String[] args) {
BigDecimal big = new BigDecimal(100);
System.out.println(big);
}
}

Compile it and run it in Java 1.4 and it prints out "100". Compile it and run it in Java 5 and it prints out "100". But now take that Java 5 compiled class (e.g., javac -target 1.4 -source 1.4 BigDecimalTest.java) and run it in Java 1.4 and you get:

Exception in thread "main" java.lang.NoSuchMethodError:
java.math.BigDecimal.(I)V
at BigDecimalTest.main(BigDecimalTest.java:5)

The problem is that Java 5 introduced a new constructor for BigDecimal that takes an int. So once compiled in Java 5, the class expects to find a constructor to match that signature and when run in Java 1.4, it blows up spectacularly. Nasty little mess.

2 comments:

Anonymous said...

The javac documentation is very clear on how to cross-compile. If you follow the instructions, it will work. See http://java.sun.com/j2se/1.5/docs/tooldocs/windows/javac.html#crosscomp-options

sundog said...

I was missing the "-bootclasspath" argument. I suppose my new conclusion is not (necessarily) "to be sure to use the compiler that matches your production version of Java" but rather "to be sure to compile against the the libraries that match your production version of Java". A day later, it seems like such a rookie mistake. But hopefully someone else will read my post (and your comment) and save themselves some time. Thanks for the pointer, Neal.