将 Java 7 编译为 Java 6
我知道 Java 7 的运行时功能在 Java 6 中不可用,但由于没有添加新的字节代码,新的字节代码 invokedynamic
仅与非相关-Java 语言,我想知道将 Java 7 源代码(新的 switch
语句、菱形运算符)转换为纯 Java 6(即能够开始将源代码转换为 Java)有多难7 且不失去 Java 6 兼容性)。
有什么指点吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
据我所知,目前这个问题还没有解决办法。最好的选择是扩展 retrotranslator 来处理 Java 1.7 结构。菱形运算符应该非常简单,因为它根本不需要修改字节码。
您的说法“没有添加新的字节码”是不正确的:有一个新的invokedynamic字节码,更重要的是,在某些情况下生成的字节码对于1.6 JRE无效,因此retrotranslator必须解决这个问题。
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.
将 Java 7 javac 输出的 .class 文件标记为版本 1.6.0(即 0x32)
(根据 http://en。 wikipedia.org/wiki/Java_class_file#General_layout)
如果将其(使用 $1 作为文件名)放入
j6patch
中,则可以执行所有类文件与:我在大型(约 4.8 MB jar)代码库上使用了它,甚至在 java 6 jar 上使用了
RetroTranslator
,因此可以在 Java 5 中运行的应用程序上使用 Java 7 语言功能。 Java 7 编译器 (javac
) 进行了大量额外的优化(例如转义分析),从而非常显着地提高了性能。将
RetroTranslator
与-verify -target 1.5
和 JRE 1.6 运行时 jar 一起使用,可以验证是否没有使用 Java 7 运行时功能。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.你是对的,Java 不使用 invokedynamic 指令,但是还有一些其他相关的更改可以在 Java 中使用。 Invokedynamic 依赖于新的“动态链接机制 - 方法句柄”,其中对 invokevirtual 指令也进行了一些更改。您可以在本文的“A”部分中找到更多详细信息新的动态联动机制:方法句柄。
方法句柄还提供了反射的更快替代方案,因此在 Java 中很有用。使用方法句柄将代码转换为 Java 6 是不可能的,因为该功能依赖于 Java 7 VM。
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.
这可能需要一些工作,但请尝试以下操作:
将 Eclipse 的 Java 编译器添加到您的类路径中。它位于插件
org.eclipse.jdt.core
中(在文件夹plugins
中搜索org.eclipse.jdt.core_*.jar
) 。该 JAR 包含编译器和解析器。您可以自己调用解析器,然后 使用
ASTVisitor
遍历解析树。然后,您可以修改树并从中创建新的源代码,您可以像往常一样进行编译。
甚至可以在编译器生成字节代码之前“预处理”AST 树;这将为您节省“将源代码写回磁盘并从那里编译它们”的步骤。
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.