2017-09-05 90 views
4

雖然學習java9 StringConcatFactory類我不明白爲什麼下面的代碼與MethodHandles.publicLookup()拋出StringConcatException異常,而如果使用MethodHandles.lookup()一切工作正常。StringConcatFactory中的異常 - Java 9

按照查找的Java文檔:

「查找 - 代表與無障礙呼叫者的 權限查詢上下文」

StringConcatFactory.makeConcat(MethodHandles.publicLookup(), 
"abc",MethodType.methodType(String.class));//Exception Here 


StringConcatFactory.makeConcat(MethodHandles.lookup(), 
"abc", MethodType.methodType(String.class)); //Working fine 

我不知道我在哪裏錯了?請幫我理解這種行爲。

+0

java9是beta狀態。請在甲骨文詢問這是否是一個錯誤 – Jens

+3

正如我的答案所示:您可能想搭建一個[mcve]。你至少應該在這裏提供異常堆棧跟蹤。 – GhostCat

+0

你的代碼是什麼'concatType'?你會得到什麼例外? – nullpointer

回答

4

makeConcat的Javadoc說,關於第一個參數:

查找代表與主叫方

查找範圍內通過publicLookup沒有這些返回的可訪問權限的查找範圍內特權。

即使您連接一無所有,除了仍然會被拋出:

MethodType concatType = MethodType.methodType(String.class); // No arguments, returns String 
StringConcatFactory.makeConcat(MethodHandles.publicLookup(), "abc", concatType); // Exception 

因爲上下文的訪問權限在StringConcatFactory#doStringConcat檢查:

if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) { 
    throw new StringConcatException("Invalid caller: " + 
      lookup.lookupClass().getName()); 
} 

的情況下需要一個私人查找模式,並且publicLookup沒有它:

System.out.println((MethodHandles.publicLookup().lookupModes() 
    & MethodHandles.Lookup.PRIVATE) != 0); // false 
System.out.println((MethodHandles.lookup().lookupModes() 
    & MethodHandles.Lookup.PRIVATE) != 0); // true 
3

publicLookup()的Javadoc說:

返回這是可信的最低限度一個查找對象。

lookup()

返回與全功能的查找對象來模擬來電者的所有受支持字節碼的行爲。這些功能包括對來電者的私人訪問。查找對象上的工廠方法可以爲調用者通過字節碼訪問的任何成員(包括受保護和專用字段和方法)創建直接方法句柄。該查找對象是可以委託給可信代理的功能。

而對於makeConcat()的Javadoc最後說:

拋出StringConcatException - 如果有任何這裏所描述的聯動不變的被侵犯。

鑑於該問題確實包含任何更多的細節事實上,最有可能的答案是:你這裏有某種形式的「許可」的問題。也許你試圖「串聯」一些在使用「最小信任」時根本不可用的東西。

4

主要的原因是在你的情況下,當一個publicLookup

StringConcatFactory.makeConcat(MethodHandles.publicLookup(), "abc", MethodType.methodType(String.class)); 

可以扔在另一方面一個StringConcatException一會兒,lookup

StringConcatFactory.makeConcat(MethodHandles.lookup(), "abc", MethodType.methodType(String.class)); 

會正常工作時的方法句柄創建用於訪問一個包的私有類的類的私有成員。

如由@GhostCat鏈接以及

publicLookup => PUBLIC_LOOKUP => (PUBLIC|UNCONDITIONAL) modes 

Javadoc of publicLookup指出返回其被最低限度地受信任的查找對象。查找有 PUBLICUNCONDITIONAL modes它只能用於創建方法 處理公共類公共類的公共成員無條件地導出 。

而對於lookup

lookup => (lookupClass => Reflection.getCallerClass, FULL_POWER_MODES => (ALL_MODES & ~UNCONDITIONAL)) 

返回與全功能的查找對象來模擬來電者的所有 支持字節碼的行爲。這些功能包括 私人訪問調用者。查找對象上的工廠方法可以通過 爲調用者通過字節碼訪問 的任何成員(包括受保護和專用字段和方法)創建直接方法句柄。 此查找對象是一種可委派給可信 代理的功能。

不要將它存儲在不受信任的代碼可以訪問它的地方。 此方法對呼叫者敏感,這意味着它可能會向不同的呼叫者返回 不同的值。

對於任何給定呼叫者類C,通過該調用返回的查找對象 具有等效功能由JVM 供給到invokedynamic指令在 同一呼叫者類C.

執行的自舉方法的任何查找對象