當前位置:首頁 » 操作系統 » hotspot源碼

hotspot源碼

發布時間: 2024-11-26 01:33:05

1. JVM角度看方法調用-MethodHandle篇

在我們日常編程中,方法調用主要涉及三種方式:直接調用、反射調用、以及 MethodHandle 調用。這一系列文章旨在深入探討這三種調用方式的原理和性能分析,文章基於 JDK 1.8 版本進行闡述。在前一篇文章中,我們總結了反射調用的諸多缺點,影響性能,因此建議在熱點代碼中使用 MethodHandle 替代反射調用。通過與極致優化後的反射調用進行比較,我們發現 MethodHandle 在性能和直接調用方面幾乎不相上下,這背後的原因是通過深入剖析 HotSpot 源碼得以揭示。

接下來,我們逐一揭開 MethodHandle 的神秘面紗。首先,讓我們明確,MethodHandle 是一個強類型的引用,能夠直接執行,類似於反射中的 Method 類,是對目標方法的引用。它被比喻為函數指針,可以指向靜態方法或實例方法、構造器或欄位。MethodHandle 的執行通過 `invoke` 和 `invokeExact` 方法實現,其中 `invokeExact` 要求參數類型與底層方法的參數完全匹配,而 `invoke` 在參數類型不匹配時會做適當的調整,如包裝類型。

MethodHandle 在 JDK 7 中首次引入,其相關核心類包括 MethodType 和 MethodHandles.Lookup。MethodType 用於確認方法句柄是否適配,由所指向方法的參數類型和返回類型組成;MethodHandles.Lookup 用於創建方法句柄,提供多個 API,既可以使用反射 API 中的 Method 來查找,也可以根據類、方法名以及方法句柄類型來查找。

在實際應用中,我們可以通過以下例子創建 MethodHandle 並進行方法調用。例如,嘗試在外部類 MethodHandleDemo 中調用 Animal 類中的私有方法 calculation(int one, int two)。若直接使用反射調用,可能會遇到外部類無法訪問 Animal 類中私有方法句柄的異常。然而,通過修改 MethodHandles.Lookup 的獲取方式,改為調用 Animal 中的 getLookup() 方法,此時外部類可以正常調用私有方法,說明方法句柄的訪問許可權不取決於句柄的創建位置,而是取決於 Lookup 對象的創建位置。

MethodHandle 在設計時就將方法修飾符許可權檢查放在了通過 MethodHandles.Lookup 獲取 MethodHandle 的階段,而調用時則不會進行許可權檢查,避免了重復的開銷。這正是 MethodHandle 相對於反射調用的一個顯著優勢。

接下來,我們深入探討 MethodHandle 調用的原理。首先,我們關注 MethodHandle 的動態簽名。在編譯時,javac 會對 MethodHandle 的 `invoke` 方法進行動態簽名處理,與普通的 `invokevirtual` 指令不同,它根據實際參數和返回類型派生符號類型描述符。此外,通過 @PolymorphicSignature 註解,可以實現多態簽名處理。進一步執行時,若簽名不一致,會拋出異常。

然後,我們解釋了 `invoke` 方法的調用實際上不是通過 JNI(Java Native Interface)進行 native 方法調用,而是執行 `invokehandle` 指令。這一過程發生在類載入階段,JVM 會掃描類中的所有方法,對位元組碼進行優化,將 `invokehandle` 指令重寫為其他指令,從而實現 MethodHandle 的內聯優化。這一機制同時解答了為什麼 MethodHandle 雖然是一個 native 方法,卻可以被 JIT(Just-In-Time)編譯器進行內聯優化的問題。

在解釋 `invokehandle` 指令後,我們分析了如何從 `MethodHandle.invoke()` 調用到實際執行的 Java 代碼中的 `java.lang.invoke.LambdaForm$MH/140435067.invoke_MT()` 方法。通過剖析 HotSpot 源碼,我們發現 `invokehandle` 指令執行時會調用 `java.lang.invoke.MethodHandleNatives::linkMethod()` 方法,該方法返回一個 `MemberName` 對象,該對象描述了一個具體的方法。通過 `MemberName` 對象,JIT 可以直接訪問方法的實現,從而避免了後續的解析過程,實現了高效的調用。

我們還探討了 `final` 關鍵字對 MethodHandle 性能的影響。標記為 `final` 的 MethodHandle 可以被更有效地內聯,從而更接近直接調用的性能。通過分析 `MethodHandle.invoke()` 調用棧以及 HotSpot 源碼,我們發現 `final` 關鍵字的使用與否,直接關繫到後續調用棧鏈路能否被內聯,從而影響性能。

最後,我們注意到在 `MethodHandle` 的調用鏈路中,某些關鍵步驟,如 `linkMethod`,會在第一次調用時執行,之後的調用則從常量池中獲取緩存。理解這些細節有助於我們更好地優化代碼性能,尤其是在涉及大量方法調用的場景中。

2. 請教hotspot源碼中關於Serialization Page的問題

由於讀sync_state的過程不是原子的,存在一個可能的場景是thread A剛讀到sync_stated,且其值是_not_synchronized,這時thread A被搶占,CPU調度給了准備發起GC的線程(不妨稱為thread B),該線程將sync_stated設置為了_synchronizing,然後讀其他線程的狀態,看其他線程是否都已經處於block狀態或者_thread_in_native狀態,是的話該線程就可以開始GC了,否則它還需要等待。

熱點內容
密碼萬能鑰匙的密碼怎麼看密碼 發布:2024-11-26 03:46:12 瀏覽:998
wds橋接後副路由器如何改無線密碼 發布:2024-11-26 03:41:54 瀏覽:474
編程要求電腦什麼配置高 發布:2024-11-26 03:41:09 瀏覽:467
抗解壓模擬器軟體下載 發布:2024-11-26 03:27:33 瀏覽:933
python獲取文件列表 發布:2024-11-26 03:18:28 瀏覽:222
減刑演算法 發布:2024-11-26 03:18:27 瀏覽:182
微信登錄忘記密碼怎麼辦啊 發布:2024-11-26 03:15:31 瀏覽:108
編碼與加密 發布:2024-11-26 03:07:45 瀏覽:873
蘋果7照片怎麼加密碼 發布:2024-11-26 02:44:57 瀏覽:932
葯網源碼 發布:2024-11-26 02:39:28 瀏覽:876