Heim  >  Artikel  >  Java  >  Verstehen Sie die JVM-Escape-Analyse in 3 Minuten

Verstehen Sie die JVM-Escape-Analyse in 3 Minuten

Java后端技术全栈
Java后端技术全栈nach vorne
2023-08-15 16:39:171260Durchsuche

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:

  1. Synchronisierte Eliminierung: Wenn durch die Escape-Analyse festgestellt wird, dass auf ein Objekt nur von einem Thread zugegriffen werden kann, können die Operationen für dieses Objekt ausgeführt werden asynchron.
  2. Zuweisung auf dem Stapel: Wenn Sie sicher sind, dass ein Objekt nicht aus dem Thread entweicht, wäre es eine sehr gute Idee, diesem Objekt Speicher auf dem Stapel zuzuweisen. Der vom Objekt belegte Speicherplatz kann freigegeben werden mit dem Stapelrahmen zerlegt und zerstört.
  3. Skalare Ersetzung: Wenn bei der Escape-Analyse festgestellt wird, dass auf ein Objekt nicht mit externen Methoden zugegriffen werden kann, und dieses Objekt zerlegt werden kann, erstellt das Programm dieses Objekt möglicherweise nicht, wenn es tatsächlich ausgeführt wird, sondern erstellt direkt mehrere davon . Dann verwendet diese Methode stattdessen Mitgliedsvariablen. Nach der Aufteilung des Objekts können die Mitgliedsvariablen des Objekts auf dem Stapel zugewiesen, gelesen und geschrieben werden.

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. 🎜

Synchronisierungseliminierung

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.

Zuweisung auf dem Stapel

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.

Skalare Ersetzung

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:Java后端技术全栈. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen