2017-09-05 1 views
4

Tout en apprenant java9 StringConcatFactory classe je suis incapable de comprendre pourquoi le code suivant avec MethodHandles.publicLookup() jette StringConcatException exception tandis que si MethodHandles.lookup() est utilisé tout fonctionne bien.Exception dans StringConcatFactory - Java 9

Comme par docs java de recherche:

« recherche - Représente un contexte de recherche avec l'accessibilité privilèges de l'appelant »

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


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

Je ne sais pas où je me trompe ? S'il vous plaît, aidez-moi à comprendre ce comportement.

+0

java9 est le statut bêta. s'il vous plaît demander à Oracle s'il s'agit d'un bug – Jens

+3

Comme ma réponse l'indique: vous voulez probablement mettre en place un [mcve]. Vous devriez au moins fournir la trace de pile d'exception ici. – GhostCat

+0

Qu'est-ce que 'concatType' pour votre code? et quelle exception obtenez-vous? – nullpointer

Répondre

4

Le javadoc pour makeConcat dit au sujet du premier paramètre:

recherche Représente un contexte de recherche avec les privilèges d'accessibilité de l'appelant

Le contexte de recherche retourné par publicLookup ne pas les privilèges

Même si vous concaténer rien, l'exception sera toujours jeté:

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

Parce que les privilèges d'accès du contexte sont vérifiées dans StringConcatFactory#doStringConcat:

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

Le cadre a besoin d'un mode de recherche privée et un publicLookup ne l'a pas:

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

Le javadoc pour publicLookup() dit:

Renvoie un objet de recherche qui est digne de confiance peu.

contre lookup():

Renvoie un objet de recherche avec des capacités complètes pour émuler tous les comportements bytecode pris en charge de l'appelant. Ces fonctionnalités incluent un accès privé à l'appelant. Les méthodes d'usine de l'objet de recherche peuvent créer des poignées de méthodes directes pour tout membre auquel l'appelant a accès via des codes secondaires, y compris des champs et des méthodes protégés et privés. Cet objet de recherche est une fonctionnalité qui peut être déléguée à des agents de confiance.

Et le javadoc pour makeConcat() dit enfin:

lancers francs StringConcatException - Si l'un des liens décrits ici sont invariants violés.

Compte tenu du fait que la question ne pas contiennent pas plus de détails, la réponse la plus probable est la suivante: vous avez une sorte de problème « autorisation » ici. Peut-être que vous essayez de "concaténer" quelque chose qui n'est tout simplement pas disponible lors de l'utilisation de "confiance minimale".

4

La raison principale comme dans votre cas lorsqu'un publicLookup:

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

peut jeter un StringConcatException alors d'autre part, la lookup

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

fonctionnerait très bien est lorsque la méthode a été créée avec sont utilisés pour accéder aux membres privés d'une classe d'une classe privée d'un package.

Comme indiqué dans le Javadoc of publicLookup lié par @GhostCat ainsi

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

Renvoie un objet de recherche qui est peu digne de confiance. La recherche a les PUBLIC et UNCONDITIONAL modes. Il ne peut être utilisé que pour créer des poignées de méthode pour des membres publics de classes publiques dans des packages exportés sans condition.

tandis que pour un lookup

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

Renvoie un objet de recherche avec des capacités complètes pour émuler tous les comportements bytecode pris en charge de l'appelant. Ces capacités comprennent l'accès privé à l'appelant. Les méthodes d'usine sur l'objet de recherche peuvent créer des poignées de méthode directe pour tous les membres auxquels l'appelant a accès aux via bytecodes, y compris les champs et méthodes protégés et privés. Cet objet de recherche est une fonctionnalité qui peut être déléguée aux agents approuvés. Ne le stockez pas dans un endroit où un code non fiable peut y accéder. Cette méthode est sensible à l'appelant, ce qui signifie qu'elle peut retourner valeurs différentes à différents appelants.

pour tout appelant donné classe C, l'objet de recherche renvoyé par cet appel a des capacités équivalentes à un objet de recherche fourni par la machine virtuelle Java le procédé d'amorçage d'une instruction invokedynamic d'exécution dans la même classe de l'appelant C.