摘要:學(xué)習(xí)添加一個字節(jié)碼。使用提供了字節(jié)碼的支持。這個啟動方法的返回值是類的對象。與區(qū)別在模擬字節(jié)碼層次的方法調(diào)用,因而可適用于所有語言在模擬層次的方法調(diào)用,僅可適用于。方法調(diào)用需要考慮到字節(jié)碼,而則不用考慮這些。
JSR 292 學(xué)習(xí)
Add a new bytecode, invokedynamic ,
that supports efficient and flexible execution of method invocations in the absence of static type information.
添加一個字節(jié)碼 invokedynamic 。用于提供在缺乏靜態(tài)類型信息時高效和靈活的執(zhí)行方法調(diào)用。
invokedynamic 是針對 JVM 的,用于更好的支持動態(tài) JVM 語言的函數(shù)調(diào)用; JSR292 實現(xiàn)則提供在 Java 語言層面上的 invokedynamic 調(diào)用。
JSR292 實現(xiàn)于 JDK7,以下為實現(xiàn)方案的類。
└─java └─lang ├─invoke | ├─CallSite | ├─ConstantCallSite | ├─MethodHandle | ├─MethodHandleProxies | ├─MethodHandles | ├─MethodHandles.Lookup | ├─MethodType | ├─MutableCallSite | ├─SwitchPoint | └─VolatileCallSite ├─ClassValue └─BootstrapMethodErrorAPI 使用
JSR292 API 提供了 invokedynamic 字節(jié)碼的 API 支持。使用基本思路
創(chuàng)建 MethodType 對象,指定方法的簽名
在 MethodHandles.Lookup 中查找類型為 MethodType 的 MethodHandle
傳入方法參數(shù)并調(diào)用 MethodHandle.invoke 或者 MethodHandle.invokeExact 方法
MethodType用于指定方法的類型,此處的方法類型與 Java 的方法判斷有點區(qū)別,Java 的方法簽名不包括 返回值 ,但是 MethodType 卻是通過 返回值 和 參數(shù)類型 來確定。并且該類型不包含 方法名 。
// 快速創(chuàng)建一個 MethodType 。 MethodType methodType = MethodType.methodType(String.class, Object.class); // 也可以通過 MethodHandle 實例獲取它要調(diào)用的方法實例 // MethodHandle handle = ... MethodType type = handle.type();
除了這兩種獲取 MethodType 的方法(實際上第二種不算,MethodHandle 對象的創(chuàng)建依賴于 MethodType)。下面還有兩種,它也是 MethodType 的靜態(tài)方法:
genericMethodType: 所有類型都是 Object 類型
fromMethodDescriptorString: 有兩個參數(shù),一個是方法描述符,該描述符是基于 字節(jié)碼 層面的描述符。之后就是一個類加載器。
當(dāng)然,創(chuàng)建完之后還可以修改返回值類型和參數(shù)類型如: changeParameterType 、 changeReturnType 等。
MethodHandles.Lookup一個工廠類,用于創(chuàng)建 MethodHandle 類對象。它可通過普通的 findXxx() 方法得到相應(yīng)的 MethodHandle 實例,也可以通過 反射類 來創(chuàng)建實例。如 lookup.unreflect(Method) 等方法。
MethodHandleMethodHandle 可看成是方法引用,它使得 Java 擁有了類似函數(shù)指針或委托的方法別名工具。
注意幾點:
引用的方法必須和 MethodHandle 的 type 保持一致。
這里提到的 type 包括 返回值 和 參數(shù)列表 。
MethodHandle 也是可執(zhí)行及可以進行轉(zhuǎn)換。
幾個 MethodHandle 方法與字節(jié)碼的對應(yīng):
MethodHandle方法 | 字節(jié)碼 | 描述 |
---|---|---|
findStatic | invokestatic | 調(diào)用靜態(tài)方法 |
findSpecial | invokespecial | 調(diào)用實例構(gòu)造方法,私有方法,父類方法。 |
findVirtual | invokevirtual | 調(diào)用所有的虛方法 |
findVirtual | invokeinterface | 調(diào)用接口方法,會在運行時再確定一個實現(xiàn)此接口的對象。 |
示例
public void example() throws Throwable { // MethodHandles.Lookup 類似于 MethodHandle 工廠類,用于創(chuàng)建 MethodHandle MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh = lookup.findStatic(String.class, "valueOf", MethodType.methodType(String.class, int.class)); String result = (String) mh.invoke(1); System.out.println("1".equals(result)); }
三種調(diào)用方式:
invokeExact: 調(diào)用此方法與直接調(diào)用底層方法一樣,需要做到參數(shù)類型精確匹配
invoke: 參數(shù)類型松散匹配,通過asType自動適配
invokeWithArguments: 直接通過方法參數(shù)來調(diào)用
CallSite當(dāng) JVM 執(zhí)行 invokedynamic 指令時,首先需要鏈接其對應(yīng)的 動態(tài)調(diào)用點 。在鏈接的時候,JVM會先調(diào)用一個啟動方法(bootstrap method)。這個啟動方法的返回值是 java.lang.invoke.CallSite 類的對象。
在通過啟動方法得到了 CallSite 之后,通過這個 CallSite 對象的 getTarget() 可以獲取到實際要調(diào)用的目標(biāo)方法句柄。
有了方法句柄之后,對這個 動態(tài)調(diào)用點 的調(diào)用,實際上是代理給方法句柄來完成的。
也就是說,對 invokedynamic 指令的調(diào)用實際上就等價于對方法句柄的調(diào)用,具體來說是被轉(zhuǎn)換成對方法句柄的invoke方法的調(diào)用。
JDK7 中提供了三種類型的動態(tài)調(diào)用點CallSite的實現(xiàn):java.lang.invoke.ConstantCallSite、java.lang.invoke.MutableCallSite和 java.lang.invoke.VolatileCallSite。
ConstantCallSite表示的調(diào)用點綁定的是一個固定的方法句柄,一旦鏈接之后,就無法修改。示例如下:
public void constantCallSite() throws Throwable { MethodType type = MethodType.methodType(String.class, int.class, int.class); MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle handle = lookup.findVirtual(String.class, "substring", type); ConstantCallSite callSite = new ConstantCallSite(handle); MethodHandle invoker = callSite.dynamicInvoker(); String result = (String) invoker.invoke("Hello", 2, 3); System.out.println(result); }MutableCallSite
表示的調(diào)用點則允許在運行時動態(tài)修改其目標(biāo)方法句柄,即可以重新鏈接到新的方法句柄上。示例如下:
/** * MutableCallSite 允許對其所關(guān)聯(lián)的目標(biāo)方法句柄通過setTarget方法來進行修改。 * 以下為 創(chuàng)建一個 MutableCallSite,指定了方法句柄的類型,則設(shè)置的其他方法也必須是這種類型。 */ public void useMutableCallSite() throws Throwable { MethodType type = MethodType.methodType(int.class, int.class, int.class); MutableCallSite callSite = new MutableCallSite(type); MethodHandle invoker = callSite.dynamicInvoker(); MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle maxHandle = lookup.findStatic(Math.class, "max", type); callSite.setTarget(maxHandle); int result = (int) invoker.invoke(3, 5); System.out.println(result == 5); MethodHandle minHandle = lookup.findStatic(Math.class, "min", type); callSite.setTarget(minHandle); result = (int) invoker.invoke(3, 5); System.out.println(result == 3); }
MutableCallSite.syncAll() 提供了方法來強制要求各個線程中 MutableCallSite 的使用者立即獲取最新的目標(biāo)方法句柄。
但這個時候也可以選擇使用 VolatileCallSite。
作用與 MutableCallSite 類似,不同的是它適用于多線程情況,用來保證對于目標(biāo)方法句柄所做的修改能夠被其他線程看到。
此處便不再提供示例,可參考 MutableCallSite。
MethodHandle 在模擬 字節(jié)碼 層次的方法調(diào)用,因而可適用于所有 JVM 語言 ;Reflection 在模擬 Java 層次的方法調(diào)用,僅可適用于 Java。
MethodHandle 可進行 JVM 的內(nèi)聯(lián)優(yōu)化,Reflection 屏蔽了 JVM ,所以完全沒有相應(yīng)的優(yōu)化。
MethodHandle 從 JVM 層次支持調(diào)用,只需要包含方法必要的信息,所以說是輕量級的,而 Reflection 是 Java Api 層次的反射調(diào)用,包含了方法的簽名、描述符以及方法屬性表中各種屬性的Java端表示方式,還包含有執(zhí)行權(quán)限等的運行期信息,所以說是重量級的。
MethodHandle 方法調(diào)用需要考慮到 字節(jié)碼,而 Reflection 則不用考慮這些。
參考JDK1.8下關(guān)于MethodHandle問題
Invokedynamic 和 MethodHandle的緣由
MethodHandle與反射Method區(qū)別
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/72496.html
摘要:物聯(lián)網(wǎng)已經(jīng)成為現(xiàn)實只要去年單獨參加過會議或者搜索過專門的技術(shù)網(wǎng)站,你現(xiàn)在會越來越清楚地注意到物物互聯(lián)正在蓬勃發(fā)展。有大量的討論在口頭上承認(rèn)了物聯(lián)網(wǎng),年這方面的激烈討論只會更多。兩年過去了,期待已久的更新應(yīng)該在月日發(fā)布。 導(dǎo)讀 如果你還在為Oracle收購Sun公司給Java社區(qū)的變化所糾結(jié),請站在Oracle的角度替它想想吧。2013年大部分時間里,Oracle都在與遺留的Java安...
摘要:摘要添加了表達(dá)式閉包和特性支持,包括方法的引用,增強類型推斷,和虛擬擴展方法。圍繞的語言功能支持包括虛擬擴展方法,這將使接口的源代碼和二進制兼容的方式演變升級。 Author:Joseph D. Darcy Organization:Oracle Owner:Brian Goetz Created:2011/11/1 Updated:2013/2/21 Type:Feature Sta...
摘要:概述是一個主要版本的發(fā)布這里介紹的是對的特性和增強的實現(xiàn)是的增強提案,包括增強建議和路線圖流程規(guī)范請求,描述了針對平臺的建議和最終規(guī)范主要變更統(tǒng)一模塊化標(biāo)準(zhǔn)這是全新的編程組件模塊,是可命名的可自描述的代碼和數(shù)據(jù)集合。 概述 java9是一個主要版本的發(fā)布 這里介紹的是Oracle對JDK9的特性和增強的實現(xiàn) JEP是JDK的增強提案,包括增強建議和路線圖流程 JSR(Java規(guī)范請...
閱讀 1534·2023-04-26 02:50
閱讀 3535·2023-04-26 00:28
閱讀 1931·2023-04-25 15:18
閱讀 3209·2021-11-24 10:31
閱讀 986·2019-08-30 13:00
閱讀 1000·2019-08-29 15:19
閱讀 1766·2019-08-29 13:09
閱讀 2975·2019-08-29 13:06