Oracle最新的Java 8更新破坏了您的工具-它是如何发生的?
如果您最近一直在關注Java世界的消息,那么您可能聽說過Oracle發布的最新Java 8構建,Java 8u11(和Java 7u65)引入了錯誤并破壞了一些流行的第三方工具,例如ZeroTurnaround的JRebel,Javassist,Google的Guice甚至Groovy本身。
JVM產生的錯誤是漫長而冗長的,但從本質上講,它們看起來像這樣:
Exception in thread "main" java.lang.VerifyError: Bad method call from inside of a branch Exception Details:Location:com/takipi/tests/dc/DepthCounter.()V @10: invokespecial…這些錯誤突然開始出現的原因是由于最新更新中的字節碼驗證程序比以前的版本更加嚴格。 與以前的版本不同,它不允許在分支代碼中調用超級構造函數。
讓我們分解一下。
Java字節碼和字節碼驗證程序
字節碼是JVM實際執行的中間語言,并且編寫編譯的.class文件。 JVM的機器代碼(如果需要)。
通過Java,通過Scala,Groovy,Clojure等將所有基于JVM的語言編譯成字節碼。 JVM不知道也不在乎源語言是什么-它只知道字節碼。
我不打算討論字節碼的工作原理 ,因為它是一個主題(或一個或多個帖子),但僅是要了解一下字節碼的樣子,以這種簡單的Java方法為例:
int add(int x, int y) {int z = x + y;return z; }編譯后,其字節碼如下所示:
ILOAD x ILOAD y IADD ISTORE z ILOAD z IRETURN當JVM將類文件從類路徑加載到內存中時,它首先必須確保字節碼有效并且代碼結構正確。 它基本上檢查正在加載的代碼是否可以實際執行。 如果字節碼正確,則該類已成功加載到內存中; 否則,將引發VerifyError ,就像帖子開頭的錯誤一樣。
此過程稱為字節碼驗證,而負責該過程的JVM部分是字節碼驗證程序。
為什么會破裂?
為了使字節碼通過驗證,它必須遵守類文件格式規范中定義的一組規則。 由于JVM最初是考慮到Java編程語言而設計的,因此許多規則都是直接從Java規則和約束派生的。
Java語言中這樣一個眾所周知的約束是,在執行其他任何操作之前,必須在構造函數中首先要做的是調用super(…)或this(…) 。 之前的任何一段代碼-您的代碼都不會編譯。 即使您沒有顯式編寫super() ,編譯器也會在構造函數的最開始為您隱式地插入它。
字節碼驗證規則中至少在紙面上存在相同的約束。 但是,事實證明,直到這些最新的JDK更新,此約束才得以完全實施。 這意味著,盡管沒有Java編譯器會允許您編譯此代碼:
public static class ClassyClass {public ClassyClass() {if (checkSomething()) {super();} else {super(getSomething());}} }…等效的字節碼將通過驗證!
ALOAD thisINVOKESTATIC checkSomething() : booleanIFEQ L2INVOKESPECIAL super() : voidGOTO L2 L1: INVOKESTATIC getSomething() : intINVOKESPECIAL super(int) : void L2: RETURN您可以在上面的簡化字節碼中看到,在第一次調用超構造函數( INVOKESPECIAL )之前,既有一個調用( INVOKESTATIC ),也有一個分支( IFEQ —“如果相等”)。
請記住,盡管以上代碼不是合法的Java,因此沒有Java編譯器會生成等效的字節碼-還有許多其他可能的工具,例如不遵循Java約束的其他JVM語言的編譯器,以及許多其他工具,例如字節碼檢測庫。 在調用super之前執行代碼的功能非常有用!
但是,Java 8 update 11帶來了更嚴格的字節碼驗證程序,該驗證程序拒絕在字節碼中使用此類構造的類,并導致引發驗證錯誤和JVM崩潰。
一方面,新的驗證程序忠于該規范,從而確保我們的JVM免受不良代碼的侵害。 另一方面,許多利用字節碼檢測的工具,例如調試器和Aspect Weavers(AOP),通常都使用上述結構。
怎么解決呢?
字節碼驗證程序的修復程序已提交 ,但尚未發布。 但是,許多受影響的工具和項目已經發布了固定版本和解決方法。
同時,如果您碰巧遇到這些錯誤之一,則可以嘗試使用-noverify命令行參數啟動JVM。 此選項指示JVM在加載類時跳過字節碼驗證。
翻譯自: https://www.javacodegeeks.com/2014/08/oracles-latest-java-8-update-broke-your-tools-how-did-it-happen.html
總結
以上是生活随笔為你收集整理的Oracle最新的Java 8更新破坏了您的工具-它是如何发生的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信步数在哪里打开
- 下一篇: Java:使用终止信号确定数据导入的状态