Dans mon cadre, j'ai une classe comme ceci:Est-ce que MethodHandle peut être utilisé par les frameworks/bibliothèques (au lieu de la réflexion traditionnelle)?
public class Foo<B, V> {
private final Method getterMethod;
...
public V executeGetter(B bean) {
try {
return getterMethod.invoke(bean);
} catch ...
}
}
Cette classe est utilisée pour appeler apporteurs de classes créées par les utilisateurs qui ne sont pas disponibles au moment de la compilation de mon cadre. Par exemple, B
peut être une classe appelée Person
. Grâce au profilage, j'ai découvert que cette méthode est horriblement lente. Le Method.invoke()
prend 40% de performance dans le profilage d'échantillonnage (même avec setAccessible(true)
), tandis qu'une implémentation non réfléchissante prend seulement une petite fraction de cette performance.
Je tiens à le remplacer est un MethodHandle
:
public class Foo<B, V> {
private final MethodHandle getterMethodHandle;
...
public V executeGetter(B bean) {
try {
return getterMethodHandle.invoke(bean);
} catch ...
}
}
Mais je reçois cette exception:
java.lang.ClassCastException: Cannot cast [Ljava.lang.Object; to Person
at sun.invoke.util.ValueConversions.newClassCastException(ValueConversions.java:461)
at sun.invoke.util.ValueConversions.castReference(ValueConversions.java:456)
at ...Foo.executeGetter(Foo.java:123)
même si bean
est une instance de Person
. Maintenant, la partie trompeuse est qu'il essaie de lancer un Object[]
(et non un Object
) à Person
. Notez que l'enveloppant dans un tableau d'objets (ce qui est une perte de performance) ne permet pas:
return getterMethodHandle.invoke(new Object[]{bean}); // Same exception
Est-il possible d'obtenir le MethodHandle
de travailler dans cette situation?
Pouvez-vous ajouter la pile complète? – BobTheBuilder
Comment avez-vous construit 'getterMethodHandle'? – Tunaki
Stacktrace ajouté. Utiliser JDK 7 pour l'enregistrement. –