Heim  >  Artikel  >  Java  >  Lösung für die Java-Ausnahme OutOfMemoryError

Lösung für die Java-Ausnahme OutOfMemoryError

不言
不言nach vorne
2019-01-30 11:08:173178Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Lösung der Java-Ausnahme OutOfMemoryError. Ich hoffe, dass er für Freunde hilfreich ist.

In der Beschreibung der Java Virtual Machine-Spezifikation können zusätzlich zum Programmzähler OOM-Ausnahmen in mehreren anderen laufenden Bereichen des Speichers der virtuellen Maschine auftreten. Hier verwenden wir Code, um zu überprüfen, was in den einzelnen Laufzeitbereichen gespeichert ist, und um zu besprechen, wie damit umzugehen ist.

Java-Heap-Überlauf

Der Java-Heap wird zum Speichern von Objektinstanzen verwendet. Solange Objekte kontinuierlich erstellt werden, gibt es einen erreichbaren Pfad zwischen GC Roots und dem Objekt Um den Garbage-Collection-Mechanismus zum Löschen dieser Objekte zu vermeiden, tritt eine Speicherüberlaufausnahme auf, nachdem die Anzahl der Objekte die maximale Heap-Kapazitätsgrenze erreicht hat.

Ausnahmereproduktion

Der Code verwendet die folgenden Parameter der virtuellen Maschine:

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

Auf diese Weise wird die Größe des Java-Heaps begrenzt 20 MB und nicht erweiterbar. Der Parameter -XX:+HeapDumpOnOutOfMemoryError ermöglicht der virtuellen Maschine, den aktuellen Speicher-Heap-Dump-Snapshot zur Analyse auszugeben, wenn eine Speicherüberlaufausnahme auftritt.

Verwenden Sie den folgenden Code zur Überprüfung:

public class HeapOOM {
    static class OOMObject {
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}

Laufergebnis:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid3460.hprof ...
Heap dump file created [28199779 bytes in 0.237 secs]

Lösung

Die OOM-Ausnahme des Java-Heapspeichers ist tatsächlich ein gemeinsamer Speicher Auf Anwendungsüberlaufausnahmen folgt häufig die Meldung „Java-Heap-Speicherplatz“, wenn sie auftreten.

Um die Anomalie in diesem Bereich zu beheben, besteht die allgemeine Methode darin, zunächst ein Speicherbildanalysetool wie MAT zu verwenden, um zu bestätigen, ob ein Speicherverlust oder ein Speicherüberlauf vorliegt.

Wenn es sich um einen Speicherverlust handelt, können Sie außerdem Tools verwenden, um die Referenzkette vom durchgesickerten Objekt zu den GC-Roots anzuzeigen und herauszufinden, wie das durchgesickerte Objekt mit den GC-Roots verknüpft ist und den Garbage Collector verhindert vom automatischen Recycling des Speicherplatzes.

Wenn es sich nicht um einen Speicherverlust handelt, d. h. die Objekte im Speicher wirklich überleben müssen, sollten Sie die Heap-Parameter der virtuellen Maschine überprüfen und sie mit dem physischen Speicher der Maschine vergleichen Sehen Sie, ob es erhöht werden kann. Versuchen Sie auf Codeebene, den Speicherverbrauch während der Ausführung des Programms zu reduzieren, wenn der Lebenszyklus einiger Objekte zu lang ist und der Status zu lange gehalten wird.

Überlauf des Stapels der virtuellen Maschine und des Stapels der lokalen Methode

Da der Stapel der virtuellen Maschine oder der Stapel der lokalen Methode in der virtuellen HotSpot-Maschine nicht unterschieden wird, gilt für HotSpot, obwohl der Parameter -Xoss vorhanden ist, In Tatsächlich ist die Stapelkapazität nur durch den Parameter -Xss festgelegt.

Ausnahmereproduktion

In einem einzelnen Thread verwendet der Code die folgenden Parameter der virtuellen Maschine:

-Xss128k

Verwenden Sie diesen Parameter, um die Stapelkapazität zu reduzieren, und verwenden Sie zur Reproduktion den folgenden Code die Ausnahme:

public class JavaVMStackSOF {

    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) throws Throwable {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

Lösung

Wenn Sie die Standardparameter der virtuellen Maschine verwenden, beträgt die Stapeltiefe in den meisten Fällen (da die von jeder Methode in den Stapel geschobene Framegröße nicht die ist). Das Gleiche gilt, daher kann man nur sagen, dass es in den meisten Fällen kein Problem ist, 1000 bis 2000 zu erreichen. Für normale Methodenaufrufe (einschließlich Rekursion) sollte diese Tiefe völlig ausreichend sein.

Wenn jedoch aufgrund der Einrichtung zu vieler Threads ein Speicherüberlauf auftritt, die Anzahl der Threads nicht reduziert werden kann oder die virtuelle 64-Bit-Maschine nicht ersetzt werden kann, besteht die einzige Möglichkeit darin, den maximalen Heap zu reduzieren und Stapelkapazität im Austausch gegen mehr Thread.

Nativer direkter Speicherüberlauf

DirectMemory-Kapazität kann durch -XX angegeben werden: MaxDirectMemorySize Wenn nicht angegeben, ist sie standardmäßig mit der identisch Maximaler Java-Heap.

Ausnahmereproduktion

Verwenden Sie die folgenden Parameter der virtuellen Maschine:

-Xmx20M -XX:MaxDirectMemorySize=10M

Verwenden Sie den folgenden Code, um die Ausnahme zu reproduzieren:

public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);//直接申请分配内存
        }
    }
}

Lösung

von Ein offensichtliches Merkmal des durch DirectMemory verursachten Speicherüberlaufs besteht darin, dass in der Heap-Dump-Datei keine offensichtlichen Ausnahmen zu sehen sind.

Wenn Sie feststellen, dass die Dump-Datei nach OOM sehr klein ist und NIO direkt oder indirekt im Programm verwendet wird, können Sie prüfen, ob dies der Grund ist.

Das obige ist der detaillierte Inhalt vonLösung für die Java-Ausnahme OutOfMemoryError. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Vorheriger Artikel:Was ist J2EE?Nächster Artikel:Was ist J2EE?