2017-09-05 3 views
4

Während java9 Lernen StringConcatFactory Klasse Ich bin nicht in der Lage zu verstehen, warum mit dem Code folgenden MethodHandles.publicLookup() wirft StringConcatException Ausnahme während, wenn MethodHandles.lookup() wird verwendet, alles funktioniert.Ausnahme in StringConcatFactory - Java 9

Wie pro Java-Dokumentation von Lookup:

"Lookup - Stell einen Lookup Zusammenhang mit der Zugänglichkeit Privilegien des Anrufers"

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


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

Ich bin nicht sicher, wo ich täusche ? Bitte hilf mir, dieses Verhalten zu verstehen.

+0

java9 ist Beta-Status. bitte fragen Sie bei Oracle, ob das ein Fehler ist – Jens

+3

Wie meine Antwort zeigt: Sie möchten wahrscheinlich eine [MCVE] aufstellen. Sie sollten hier mindestens die Ablaufverfolgung für den Ausnahme-Stack angeben. – GhostCat

+0

Was ist 'concatType' für Ihren Code? und welche Ausnahme bekommst du? – nullpointer

Antwort

4

Die javadoc für makeConcat sagt über den ersten Parameter:

Lookup einen Lookup Zusammenhang mit der Zugänglichkeit Privilegien des Anrufers Stellt

Der Nachschlag Kontext von publicLookup zurück nicht diejenigen, Privilegien.

Auch wenn Sie nichts zu verketten, wird nach wie vor die Ausnahme ausgelöst werden:

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

Da die Zugriffsrechte des Kontextes, in StringConcatFactory#doStringConcat geprüft werden:

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

Der Kontext muss einen privaten Lookup-Modus und ein publicLookup hat es nicht:

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

Die javadoc für publicLookup() sagen:

ein Lookup-Objekt zurück, das minimal vertrauenswürdig ist.

gegen lookup():

Gibt ein Lookup-Objekt mit vollen Fähigkeiten all unterstützten Bytecode Verhalten des Anrufers zu emulieren. Zu diesen Funktionen gehört der private Zugriff auf den Anrufer. Factory-Methoden für das Suchobjekt können direkte Methodenhandles für jedes Mitglied erstellen, auf das der Aufrufer über Bytecodes zugreifen kann, einschließlich geschützter und privater Felder und Methoden. Dieses Nachschlageobjekt ist eine Funktion, die an vertrauenswürdige Agenten delegiert werden kann.

Und die javadoc für makeConcat() sagt schließlich:

wirft StringConcatException - Wenn eine der Verknüpfung Invarianten hier beschriebenen verletzt werden.

Angesichts der Tatsache, dass die Frage tut nicht keine weiteren Details enthalten, die wahrscheinlichste Antwort ist: Sie irgendeine Art von „Erlaubnis“ Problem hier haben. Vielleicht versuchst du etwas zu "concatchen", was bei "minimaler Vertrauenswürdigkeit" einfach nicht verfügbar ist.

4

Der Hauptgrund wie in Ihrem Fall, wenn ein publicLookup:

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

ein StringConcatException während auf der anderen Seite werfen, die lookup

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

fein funktionieren würde, ist, wenn die Methode verwendet, erstellt Griff Greifen Sie auf private Mitglieder einer Klasse einer privaten Klasse eines Pakets zu.

Wie in der auch von @GhostCat verbunden Javadoc of publicLookup angegeben

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

Gibt ein Lookup-Objekt, das minimal vertrauenswürdig ist. Die Suche hat die PUBLIC und UNCONDITIONAL modes. Es kann nur verwendet werden, um die Methode Handles für öffentliche Mitglieder der öffentlichen Klassen in Paketen zu erstellen, die bedingungslos exportiert werden.

während für ein lookup

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

Gibt ein Lookup-Objekt mit vollen Fähigkeiten all unterstütztes Bytecode Verhalten des Anrufers zu emulieren. Diese Funktionen umfassen privaten Zugriff auf den Aufrufer. Factory-Methoden für das Suchobjekt können direkte Methodenhandles für jedes Mitglied erstellen, auf das der Aufrufer über Bytecodes zugreifen kann, einschließlich geschützter und privater Felder und Methoden. Dieses Nachschlageobjekt ist eine Funktion, die an vertrauenswürdige Agenten delegiert werden kann.

Speichern Sie es nicht dort, wo nicht vertrauenswürdiger Code darauf zugreifen kann. Diese Methode ist aufruferempfindlich, was bedeutet, dass sie verschiedene Werte an verschiedene Anrufer zurücksenden kann .

Für jede gegebenen Anrufer Klasse C, das Objekt-Lookup durch diesen Aufruf zurückgegeben hat äquivalente Funktionen zu jedem Objekt lookup durch die JVM geliefert an die Bootstrap-Methode einer invokedynamic Anweisung in die gleiche Aufrufer Klasse C. Ausführung