2017-08-18 2 views
3

In meinem aktuellen Projekt möchte ich in der Lage sein, eine Lambda-Methode „Reinstanziierung“ (weiß nicht, ob „Reinstanziierung“, obwohl das richtige Wort ist)OpenJDK 8 Lambdas Verarbeitung

Betrachten wir ein Beispiel folgende

public static void main(String[] args) throws Throwable { 
    TestUser tu = new TestUser(); 

    ITest1 lam = t->{ 
     System.out.println("whoops" + tu.toString()); 
     return 1; 
    }; 

    tu.doExec(lam); 

    calls++; 
    if(calls == 1) main(args); 
} 

Hier ich habe versucht, durch die JVM Anrufe zu debuggen, und ich bemerkte, dass JVM erstellt und MethodType und MethodHandle Objekte für die metafactory Methode (die CallSite schafft baut) und für meine Lambda-Methode. Sobald dies erledigt ist, wird linkCallSite aufgerufen. Diese Methode erstellt die CallSite und verknüpft die Lambda-Methode nur einmal mit ihr. An dieser Stelle ist meine Frage, kann ich irgendwie die Lambda CallSite und LambdaForm von der jvm löschen und irgendwie den ganzen Prozess wieder auslösen?

Und eine andere Frage, wenn sie durch die JVM Debuggen ruft ich, dass jedes Mal bemerkt, wenn JVM die Lambda-Methode ausgeführt wird, ein Verfahren Ljava/lang/invoke/LambdaForm$MH/818403870;.linkToTargetMethod(Object) aufgerufen wird, die ich nicht Source, weder in JVM cpp Quellen finden können, noch in Java. Wie genau wird diese Methode aufgerufen oder wo wird sie aufgerufen?

Ich weiß, die Frage ist irgendwie kompliziert, also bin ich offen für Ihre Fragen. Vielen Dank im Voraus.

+0

was meinst du mit "instantiate" ?? –

+0

@ ΦXocê 웃 Пepeúpa ツ Ich möchte die LamdaForms und CallSite aus dem jvm löschen, damit jvm das gesamte Instanziierungsverfahren erneut durchführen muss ... –

+0

hast du versucht, die betreffende Klasse unter einem anderen Klassenlader zu laden? – the8472

Antwort

1

kann ich irgendwie die Lambda CallSite und LambdaForm aus dem jvm löschen und irgendwie den ganzen Prozess wieder auslösen?

invokedynamic wird einen CallSite verknüpft (oder manchmal auch direkt an die Zielmethode) nur einmal an der Bytecode Auflösungszeit. Das Auflösungsergebnis wird im Konstantenpool-Cache gespeichert und anschließend nicht geändert.

Eine Möglichkeit, den Konstantenpool-Cache zurückzusetzen, besteht darin, die Klasse neu zu definieren. Ich zähle nicht, die Klasse in einem anderen ClassLoader neu zu laden, da dies technisch dasselbe ist wie das Laden einer neuen Klasse, die nicht mit einer alten Klasse zusammenhängt.

Also, um linkCallSite Sachen wieder auszulösen, können Sie Instrumentation.redefineClasses oder das Äquivalent JVM TI RedefineClasses Funktion aufrufen.

Wie genau wird diese Methode aufgerufen oder wo wird sie aufgerufen?

linkToTargetMethod ist ein Adapter dynamisch zur Laufzeit erzeugt eine MethodHandle dem spezifischen invokedynamic Bytecode verknüpft aufrufen. Es ist im Grunde die Implementierung von invokedynamic, die diesen Adapter aufruft.

Here is Die Quelle, in der dieser Adapter generiert wird.

+0

Würde das auch funktionieren, falls die Klasse nicht wirklich neu definiert wird? Bedeutung 'redefinyClasses' wird aufgerufen, aber es wird keine Änderung im Bytecode vorgenommen. Oder führt ein solcher Aufruf immer dazu, dass die JVM alles löscht, was mit diesen Klassen verbunden war? –

+0

@HaasipSatang In meinen Tests setzt 'redefinyClasses' die aufgerufene dynamische Verbindung zurück, auch wenn sie mit demselben Bytecode aufgerufen wird. Dieses Verhalten wird jedoch nicht angegeben, und die echten Produktionsanwendungen sollten sich nicht darauf verlassen. – apangin

Verwandte Themen