Als qualifizierter Java-Entwickler wissen wir alle, dass grundsätzlich alle Objekte auf dem Heap erstellt werden. Allerdings gibt es hier noch kein absolutes Wort, es bezieht sich auf im Grunde alles.
Gestern sagte ein Freund während eines Interviews, dass alle Objekte im Heap erstellt werden, und lachte dann den Interviewer aus.
Beginnen Sie mit unserem Haupttext. Lassen Sie uns heute über die Fluchtanalyse sprechen.
Escape Analysis (Escape Analysis) ist derzeit eine relativ hochmoderne Optimierungstechnologie in der Java Virtual Machine. Dies ist ein funktionsübergreifender globaler Datenflussanalysealgorithmus, der die Synchronisierungslast und den Speicher-Heap-Zuweisungsdruck in Java-Programmen effektiv reduzieren kann. Durch die Escape-Analyse kann der Java-Hotspot-Compiler den Nutzungsbereich der Referenz eines neuen Objekts analysieren und entscheiden, ob dieses Objekt dem Heap zugewiesen werden soll.
Das Grundprinzip der Escape-Analyse ist : Analysieren Sie den dynamischen Bereich von Objekten. Wenn ein Objekt in einer Methode definiert wird, kann es von externen Methoden referenziert werden, z. B. durch die Übergabe an andere Methoden als Aufrufparameter Ein Methoden-Escape; es kann sogar von externen Threads aufgerufen werden, z. B. durch Zuweisen zu Instanzvariablen, auf die in anderen Threads zugegriffen werden kann; zu hoch. Unterschiedliche Fluchtgrade.
Wenn die Escape-Analyse aktiviert ist, kann der Compiler den Code wie folgt optimieren:
In JVM können Sie über die folgenden Parameter angeben, ob die Escape-Analyse aktiviert werden soll:
-XX:+DoEscapeAnalysis
: Zeigt das Aktivieren der Escape-Analyse an (sie ist nach JDK 1.7 standardmäßig aktiviert). -XX:+DoEscapeAnalysis
:表示开启逃逸分析(JDK 1.7之后默认开启)。
-XX:-DoEscapeAnalysis
-XX:-DoEscapeAnalysis
: Stellt dar Schalten Sie die Escape-Analyse aus. 🎜Die Thread-Synchronisierung selbst ist ein relativ zeitaufwändiger Prozess. Wenn durch die Escape-Analyse festgestellt werden kann, dass eine Variable dem Thread nicht entkommt und von anderen Threads nicht darauf zugegriffen werden kann, erfolgt definitiv kein Lesen und Schreiben Aufgrund der Konkurrenz dieser Variablen können auf diese Variable implementierte Synchronisierungsmaßnahmen sicher eliminiert werden.
Zum Beispiel der folgende Code:
public void method() { Object o = new Object(); synchronized (o) { System.out.println(o); } }
sperrt 对象o
, aber der Lebenszyklus des Objekts o ist der gleiche wie der der Methode method(), sodass andere Threads nicht darauf zugreifen und keine Thread-Sicherheitsprobleme auftreten wird während der JIT-Kompilierungsphase blockiert. Optimiert, um so auszusehen:
public void method() { Object o = new Object(); System.out.println(o); }
Dies wird auch als Lock Elimination bezeichnet.
In der Java Virtual Machine ist die Zuweisung von Speicherplatz für erstellte Objekte auf dem Java-Heap für Java-Programmierer fast selbstverständlich. Objekte im Java-Heap werden gemeinsam genutzt und sind für jeden Thread sichtbar. Solange Sie über einen Verweis auf dieses Objekt verfügen, können Sie auf die im Heap gespeicherten Objektdaten zugreifen. Das Garbage-Collection-Subsystem der virtuellen Maschine recycelt Objekte, die nicht mehr im Heap verwendet werden. Der Recyclingvorgang erfordert jedoch viele Ressourcen, unabhängig davon, ob wiederverwendbare Objekte markiert und herausgefiltert oder Speicher recycelt und organisiert werden. Es gibt jedoch einen Sonderfall. Wenn die Escape-Analyse bestätigt, dass das Objekt nicht aus dem Thread entkommt, kann es für die Zuordnung auf dem Stapel optimiert werden. Dadurch entfällt die Notwendigkeit, Speicher auf dem Heap zuzuweisen, und es ist keine Speicherbereinigung erforderlich.
Zum Beispiel der folgende Code:
public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 1000000; i++) { alloc(); } Thread.sleep(100000); } private static void alloc() { User user = new User(); }
Der Code ist sehr einfach. Er besteht darin, 1 Million Mal eine Schleife zu erstellen und mit der alloc()-Methode 1 Million Benutzerobjekte zu erstellen. Das hier in der alloc()-Methode definierte Benutzerobjekt wird von anderen Methoden nicht referenziert und erfüllt daher die Anforderungen für die Zuordnung auf dem Stapel.
Die JVM-Parameter lauten wie folgt:
-Xmx2G -Xms2G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
Starten Sie das Programm und überprüfen Sie die Anzahl der Instanzen mit dem Jmap-Tool:
jmap -histo pid num #instances #bytes class name ---------------------------------------------- 1: 3771 2198552 [B 2: 10617 1722664 [C 3: 104057 1664912 com.miracle.current.lock.StackAllocationTest$User
Wir können sehen, dass das Programm insgesamt 104057 Benutzerobjekte erstellt hat, was weit weniger als 1 ist Million. Wir können die Escape-Analyse deaktivieren und noch einmal einen Blick darauf werfen:
-Xmx2G -Xms2G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
Starten Sie das Programm und überprüfen Sie die Anzahl der Instanzen mit dem Jmap-Tool:
jmap -histo 42928 num #instances #bytes class name ---------------------------------------------- 1: 628 22299176 [I 2: 1000000 16000000 com.miracle.current.lock.StackAllocationTest$User
Sie können sehen, dass nach dem Deaktivieren der Escape-Analyse insgesamt 1 Million Benutzerobjekte erstellt wurden . Im Vergleich dazu spielt die Zuordnung auf dem Stapel eine wichtige Rolle für den Heap-Speicherverbrauch und die GC.
Wenn Daten zur Darstellung nicht mehr in kleinere Daten zerlegt werden können, können die ursprünglichen Datentypen in der Java Virtual Machine (int, long und andere numerische Typen und Referenztypen usw.) nicht verwendet werden Wenn man sie weiter zerlegt, können diese Daten als Skalare bezeichnet werden. Wenn dagegen ein Datenelement weiter zerlegt werden kann, spricht man von einem Aggregat. Objekte in Java sind typische Aggregate.
Wenn die Escape-Analyse beweisen kann, dass auf ein Objekt außerhalb der Methode nicht zugegriffen wird und dieses Objekt zerlegt werden kann, erstellt das Programm dieses Objekt möglicherweise nicht, wenn es tatsächlich ausgeführt wird, sondern erstellt stattdessen direkt mehrere davon zur Verwendung durch stattdessen diese Methode verwenden.
hat den folgenden Code:
public static void main(String[] args) { method(); } private static void method() { User user = new User(25); System.out.println(user.age); } private static class User { private int age; public User(int age) { this.age = age; } }
在method()
方法中创建User对象,指定age为25,这里User不会被其他方法引用,也就是说它不会逃逸出方法,并且User是可以拆解为标量的。所以alloc()
代码会优化为如下:
private static void alloc() { int age = 25; System.out.println(age); }
尽管目前逃逸分析技术仍在发展之中,未完全成熟,但它是即时编译器优化技术的一个重要前进方向,在日后的Java虚拟机中,逃逸分析技术肯定会支撑起一系列更实用、有效的优化技术。
Das obige ist der detaillierte Inhalt vonVerstehen Sie die JVM-Escape-Analyse in 3 Minuten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!