tags:

views:

57

answers:

2

Is there a third party library to detect the use of a Java 1.5 library when compiling with a 1.5 compiler with -source 1.4 and -target 1.4? I could use a 1.4 rt.jar in the bootclasspath however I hope there is a better way. To be used, for example, to fail the compile/build if a newer library is used.

+1  A: 

It is not clear to me what you are trying to achieve. So I'm guessing that you are trying to ensure that your code is 100% Java 1.4 compatible, while also trying and make use of (hypothetical) improvements in the Java 1.5 bytecode compiler. The simple way is to do two builds:

  1. Build using Java 1.4 to check that your code is Java 1.4 library compatible.

  2. Build a second time using Java 1.5 with -source 1.4 and -target 1.4.

The catch is that this only detects static API mismatches, and will miss problems where you are using APIs reflectively or where the incompatibilities are in class behavior rather than signatures.

The other thing to note is that compiling Java on a new platform to run on an old platform is not likely to help ... if that is what you are trying to achieve.

  • The Java bytecode compilers apparently don't do much optimization, and therefore won't produce significantly faster bytecodes in newer releases.

  • The JIT compilers are likely improve significantly from one release to the next, but the JIT compiler is part of the execution platform.

  • The other place where improvements may occur is in the class libraries.

If you compile code with the JDK 1.5 javac compiler and then run on a Java 1.4 platform, you don't get the benefit of JIT compiler improvements or class library improvements.

Stephen C
+1  A: 

The curiously named Animal Sniffer is designed for this task. See Kohsuke's blog post Compiling with JDK6 and running on JDK5

It's packaged as a Maven Plugin (an example of usage is given in this answer), but can also be invoked programmatically:

 ~/code/scratch/sniff: curl http://maven.dyndns.org/2/org/jvnet/animal-sniffer/1.2/animal-sniffer-1.2.jar > animal-sniffer.jar
 ~/code/scratch/sniff: curl http://repo1.maven.org/maven2/asm/asm-all/3.1/asm-all-3.1.jar > asm-all.jar
 ~/code/scratch/sniff: curl http://maven.dyndns.org/2/org/jvnet/animal-sniffer/java1.5/1.0/java1.5-1.0.sig > java1.5-1.0.sig

 ~/code/scratch/sniff: mkdir -p target/classes
 ~/code/scratch/sniff: cd !$
cd target/classes
 ~/code/scratch/sniff/target/classes: jar xf /Users/jason/usr/scala-2.8.0.RC2/lib/scala-library.jar
 ~/code/scratch/sniff/target/classes: jar xf /Users/jason/usr/scala-2.8.0.RC2/lib/scala-compiler.jar
 ~/code/scratch/sniff/target/classes: cd -
/Users/jason/code/scratch/sniff
 ~/code/scratch/sniff: scala -classpath animal-sniffer.jar:asm-all.jar
Welcome to Scala version 2.8.0.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import org.jvnet.animal_sniffer._
import org.jvnet.animal_sniffer._

scala> import collection.JavaConversions._
import collection.JavaConversions._

scala> val ignored = collection.mutable.Set("scala/*", "ch/*", "jline/*", "org/apache/*")
ignored: scala.collection.mutable.Set[java.lang.String] = Set(org/apache/*, jline/*, scala/*, ch/*)

scala> val sc = new SignatureChecker(new java.io.FileInputStream("java1.5-1.0.sig"), ignored)
sc: org.jvnet.animal_sniffer.SignatureChecker = org.jvnet.animal_sniffer.SignatureChecker@2a65dbe8

scala> sc.process(new java.io.File("target/classes"))
Undefined reference: java/util/concurrent/locks/LockSupport.park(Ljava/lang/Object;)V in target/classes/scala/concurrent/forkjoin/ForkJoinPool$WaitQueueNode.class
Undefined reference: sun/misc/Unsafe.putOrderedObject(Ljava/lang/Object;JLjava/lang/Object;)V in target/classes/scala/concurrent/forkjoin/ForkJoinWorkerThread.class
Undefined reference: sun/misc/Unsafe.putOrderedInt(Ljava/lang/Object;JI)V in target/classes/scala/concurrent/forkjoin/ForkJoinWorkerThread.class
Undefined reference: java/util/concurrent/atomic/AtomicReferenceFieldUpdater.lazySet(Ljava/lang/Object;Ljava/lang/Object;)V in target/classes/scala/concurrent/forkjoin/LinkedTransferQueue$QNode.class
Undefined reference: java/util/concurrent/locks/LockSupport.park(Ljava/lang/Object;)V in target/classes/scala/concurrent/forkjoin/LinkedTransferQueue.class
Undefined reference: java/util/concurrent/locks/LockSupport.parkNanos(Ljava/lang/Object;J)V in target/classes/scala/concurrent/forkjoin/LinkedTransferQueue.class
retronym