I'm aware that the runtime features of Java 7 are not available with Java 6 but since no new byte code has been added the new byte code invokedynamic
is only relevant for non-Java languages, I was wondering how hard it would be to convert Java 7 source code (new switch
statement, diamond operator) to pure Java 6 (i.e. to be able to start to convert the source to Java 7 without losing Java 6 compatibility).
Any pointers?
It's probably some work but try this:
Add Eclipse's Java Compiler to your classpath. It's in the plugin
org.eclipse.jdt.core
(search fororg.eclipse.jdt.core_*.jar
in the folderplugins
).This JAR contains the compiler and the parser. You can invoke the parser yourself and then use the
ASTVisitor
to traverse the parse tree.You can then modify the tree and create the new source code from this that you can compile as usual.
It might even be possible to "preprocess" the AST tree before the compiler generates byte code; this would save you the "write sources back to disk and compile them from there" step.
You are right that invokedynamic instruction is not used by Java, however there are some other related changes which can be used in Java. Invokedynamic relies on a new 'Dynamic Linkage Mechanism - Method Handles' for which there are some changes to the invokevirtual instruction as well. You can find more details in this article in the section 'A New Dynamic Linkage Mechanism: Method Handles'.
Method handles also provide a faster alternative to reflection, and hence are useful in Java. Converting code using method handles to Java 6 would not be possible as the feature relies Java 7 VM.
Mark a .class file output by Java 7 javac with version 1.6.0 (i.e. 0x32)
(according to http://en.wikipedia.org/wiki/Java_class_file#General_layout)
If you put that (using $1 for the filename) into
j6patch
you can do all class files with:I used this on a large (~4.8 MB jar) code base and even used
RetroTranslator
on the java 6 jar so Java 7 language features can be used on an app that runs in Java 5. Also the Java 7 compiler (javac
) does lots of extra optimizations (e.g. escape analysis) that very noticeably improves performance.Using
RetroTranslator
with-verify -target 1.5
and JRE 1.6 runtime jars allows to verify that no Java 7 runtime features are used.As far as I know, there is no solution for this problem at the moment. The best bet would be to extend retrotranslator to deal with Java 1.7 constructs. The diamond operator should be very easy, since it requires no bytecode modification at all.
Your statement "no new byte code has been added" is not correct: There is a new invokedynamic byte code and more importantly there are several cases where the generated bytecode will not be valid for 1.6 JREs, so retrotranslator would have to fix that.