Ja, es gibt eine Optimierung, um die Reflektionskosten zu reduzieren, obwohl sie hauptsächlich in der Klassenbibliothek und nicht in JVM implementiert ist.
Vor Java 1.4 Method.invoke
arbeitete über einen JNI-Aufruf an VM-Laufzeit. Jeder Aufruf erforderte mindestens zwei Übergänge von Java zu Native und zurück zu Java. Die VM-Laufzeitumgebung analysierte eine Methodensignatur, verifizierte, dass die übergebenen Argumente korrekt waren, führte Boxing/Unboxing aus und erstellte einen neuen Java-Frame für eine aufgerufene Methode. All das war ziemlich langsam.
Seit Java 1.4 Method.invoke
verwendet dynamische Bytecode-Generierung, wenn eine Methode mehr als 15 Mal aufgerufen wird (konfigurierbar über sun.reflect.inflationThreshold
Systemeigenschaft). Eine spezielle Java-Klasse, die für den Aufruf der angegebenen bestimmten Methode verantwortlich ist, wird in der Laufzeit erstellt. Diese Klasse implementiert sun.reflect.MethodAccessor welche java.lang.reflect.Method
Delegierten Anrufe zu.
Der Ansatz mit dynamischer Bytecode-Generation ist viel schneller, da es
- nicht von JNI-Overhead nicht leiden;
- muss die Methodensignatur nicht jedes Mal analysieren, da jede über Reflection aufgerufene Methode ihren eigenen eindeutigen MethodAccessor hat;
- kann weiter optimiert werden, z.B. diese MethodAccessors können aus allen gängigen JIT-Optimierungen wie inlining, Konstantenpropagation profitieren, Autoboxing Eliminierung usw.
Beachten Sie, dass diese Optimierung meist in Java code ohne JVM Unterstützung umgesetzt wird. Das einzige, was HotSpot VM tut, um diese Optimierung zu ermöglichen, ist das Überspringen der Bytecode-Verifizierung für solche generierten MethodAccessors. Andernfalls würde der Verifizierer beispielsweise nicht erlauben, private Methoden aufzurufen.
Vielleicht hat dies etwas mit ['MethodHandles.Lookup # unreflect()'] (http://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.Lookup) zu tun. html # nicht reflect-java.lang.reflect.Method-)? – fge