2011-10-05 56 views
27

我知道Java 7的運行時功能不適用於Java 6,但自從沒有添加新的字節代碼新的字節代碼invokedynamic僅與非Java語言相關,我想知道如何將Java 7源代碼(新的switch語句,鑽石操作符)轉換爲純Java 6(即能夠開始將源代碼轉換爲Java 7而不失去Java 6兼容性)。將Java 7編譯爲Java 6

任何指針?

+3

我很想知道動機。只是學術興趣? –

+0

實際上,在Java 7中添加了一個新的字節碼:'invokedynamic'(當編譯Java源代碼時Java編譯器不會生成它)。 – Jesper

+0

我認爲invokedynamic支持確實意味着添加新的字節碼? – SteveD

回答

6

馬克在Java 7的javac一個.class輸出與1.6.0版本(即0x32)文件

 
printf "\x00\x00\x00\x32" |dd of=Example.class seek=4 bs=1 count=4 conv=notrunc 

(根據http://en.wikipedia.org/wiki/Java_class_file#General_layout

如果你把(使用$ 1名)到j6patch你可以做所有的類文件用:

 
find . -name \*.class |xargs -I {} ./j6patch {} 

我用這對一個大的(〜4.8 MB JAR)的代碼庫,甚至在Java中使用RetroTranslator 6 jar,因此可以在運行於Java 5的應用程序上使用Java 7語言功能。此外,Java 7編譯器(javac)還會執行許多額外的優化(例如,逃逸分析),這顯着提高了性能。

使用RetroTranslator-verify -target 1.5和JRE 1.6運行時jar允許驗證是否沒有使用Java 7運行時功能。

+0

你嘗試過嗎?它在實踐中有多好? –

+0

是的,在一個很大的(〜4.8 MB的jar)代碼庫上,甚至在Java 6 jar中使用了RetroTranslator,因此可以在運行於Java 5的應用程序上使用Java 7語言功能。此外,Java 7編譯器(javac)額外的優化(例如逃逸分析)可以顯着提高性能。 – karmakaze

+2

此外,您可以使用RetroTranslator與-verify -target 1.5和JRE 1.6運行時jar來驗證是否使用了Java 7運行時。 – karmakaze

11

據我所知,目前沒有解決這個問題的方法。最好的辦法是擴展retrotranslator來處理Java 1.7構造。鑽石操作員應該非常容易,因爲它根本不需要字節碼修改。

您的語句「沒有添加新的字節代碼」是不正確的:有一個新的invokedynamic字節代碼,更重要的是有幾種情況下生成的字節代碼在1.6 JRE中無效,所以retrotranslator必須解決該問題。

+0

你能舉一個例子,說明生成的字節代碼對於Java 6 VM無效嗎? 'invokedynamic'不被Java本身使用,它只適用於像Groovy或Jython這樣的動態語言(並且兩者都可以沒有它)。 –

+2

您將不得不經過Java SE 7規範的附件3(http://download.oracle.com/otndocs/jcp/java_se-7-final-eval-spec/index.html),它包含PDF在Java SE 6中的差異。粗略一瞥似乎確實好像所有重大更改(例如新的常量池類型)都與invokedynamic支持相關。 –

+0

問題是字節代碼版本號包含在類文件中,所以1.6 JVM不會加載1.7類文件。 –

3

您說得對,invokedynamic指令並未被Java使用,但是還有其他一些可以在Java中使用的相關更改。 Invokedynamic依賴於一種新的「動態鏈接機制 - 方法處理」,其中對invokevirtual指令也進行了一些更改。您可以在「新動態連桿機構:方法手柄」一節中找到this article的更多詳細信息。

方法句柄還提供了更快的反射替代方法,因此在Java中很有用。由於該功能依賴於Java 7 VM,所以不可能將使用方法句柄的代碼轉換爲Java 6。

+0

對引用文章的閱讀似乎表明新的'動態鏈接機制'不支持任何新的字節碼,而是支持java.dyn(java.lang.invoke.MethodHandle)運行時支持。當然,應該檢查字節碼以查看Java 6兼容性沒有引用該字節碼。 – karmakaze

2

這也可能是一些工作,但試試這個:

Eclipse的Java編譯器添加到您的類路徑。它位於插件org.eclipse.jdt.core(在文件夾plugins中搜索org.eclipse.jdt.core_*.jar)。

此JAR包含編譯器和解析器。您可以自己調用解析器,然後使用use the ASTVisitor來遍歷解析樹。

然後,您可以修改樹並從中創建新的源代碼,您可以照常編譯。

在編譯器生成字節碼之前,甚至可以「預處理」AST樹;這將爲您節省「將源代碼寫回磁盤並從那裏編譯」步驟。