OOM bedeutet, dass im Programm eine Schwachstelle vorliegt, die durch den Code oder die JVM-Parameterkonfiguration verursacht werden kann. In diesem Artikel erfahren die Leser, wie sie Fehler beheben können, nachdem ein Java-Prozess OOM ausgelöst hat.
Es wird oft gesagt, dass man Ehrfurcht vor der Produktionsumgebung hat, und das schnelle Lösen von Problemen ist auch ein Zeichen der Ehrfurcht
OOM steht für „Out Of Memory“, was bedeutet Der Speicher ist erschöpft. Wenn die JVM nicht über genügend Speicher verfügt, um dem Objekt Speicherplatz zuzuweisen, und der Garbage Collector keinen Speicherplatz zum Recyceln hat, wird dieser Fehler ausgegeben
Warum tritt OOM auf? Dies wird im Allgemeinen durch diese Probleme verursacht Zuweisung: Der JVM-Initialisierungsspeicher ist klein und das Unternehmen verwendet viel Speicher. Oder die Zuweisung von Speicher in verschiedenen JVM-Bereichen ist unangemessen. Code-Schwachstelle: Ein bestimmtes Objekt wird häufig beantragt, aber danach nicht freigegeben wird nicht mehr verwendet, was zu einer Speichererschöpfung führt
Gemeinsame OOM-Typen sind die folgenden: Überlauf der permanenten Java7-Generierung (Methodenbereich), der zum Speichern von Daten wie Klasseninformationen, Konstanten, statischen Variablen und vom Just-in-Time-Compiler kompiliertem Code verwendet wird, die von der virtuellen Maschine geladen wurden. Wenn eine Klasse zum ersten Mal geladen wird, werden Metadaten in der permanenten Generation gespeichert. Normalerweise treten sie in einer großen Anzahl von Klassenobjekten oder JSP-Seiten auf oder werden durch die Verwendung der dynamischen Proxy-Technologie von CgLib verursacht.
我们可以通过 -XX:MaxPermSize
修改方法区大小-XX:PermSize
和 -XX:MaxPermSize
修改方法区大小
Java8 将永久代变更为元空间,报错:java.lang.OutOfMemoryError: Metadata space,元空间内存不足默认进行动态扩展
java.lang.StackOverflowError
虚拟机栈溢出,一般是由于程序中存在 死循环或者深度递归调用 造成的。如果栈大小设置过小也会出现溢出,可以通过 -Xss
设置栈的大小
虚拟机抛出栈溢出错误,可以在日志中定位到错误的类、方法
java.lang.OutOfMemoryError: Java heap space
Java 堆内存溢出,溢出的原因一般由于 JVM 堆内存设置不合理或者内存泄漏导致
如果是内存泄漏,可以通过工具查看泄漏对象到 GC Roots 的引用链。掌握了泄漏对象的类型信息以及 GC Roots 引用链信息,就可以精准地定位出泄漏代码的位置
如果不存在内存泄漏,就是内存中的对象确实都还必须存活着,那就应该检查虚拟机的堆参数(-Xmx 与 -Xms),查看是否可以将虚拟机的内存调大些
小结:方法区和虚拟机栈的溢出场景不在本篇过多讨论,下面主要讲解常见的 Java 堆空间的 OOM 排查思路
假设我们 Java 应用 PID 为 15162,输入命令查看 JVM 内存分布 jmap -heap 15162
Java8 将永久代变更为元空间,报错:java.lang.OutOfMemoryError: Metadata java.lang.StackOverflowError
虚拟机栈溢出,一般是由于程序中存在 死循环或者深度递归调用 造成的。如果栈大小设置过小也会出现溢出,可以通过
-Xss 设置栈的大小</codestil></p>🎜虚拟机抛出栈溢出错误,可以在日志中定位到错误的类、方法🎜🎜<strong>java.lang.OutOfMemoryError: Java ap-Speicherplatz</strong>🎜🎜<strong>Java 堆内存溢出</strong>,溢出的原因一般由于 JVM掌握了泄漏对象的类型信息以及 GC Roots引用链信息,就可以精准地定位出泄漏代码的位置🎜🎜如果不存在内存泄漏,就是内存中的对象确实都还必须存活着,那就应该检查虚拟机的堆参数(-Xmx 与 -Xms)查看是否可以将虚拟机的内存调大些🎜🎜小结:方法区和虚拟机栈的溢出场景不在本篇过多讨论,下面主要讲解常见的 Java 堆空间的 OOM 排查思路🎜<h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: fett;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"> <span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px; border-top-left-radius: 3px;margin-right: 3px;">查看 JVM-Modell</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid # efebe9;border-right: 20px solid transparent;"> </span> </h2>🎜假设我们 Java 应用 PID 为 15162,输入命令查看 JVM 内存分布 <code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: „Operator Mono“ , Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">jmap -heap 15162🎜 🎜通过查看 JVM 内存分配以及运行时使用情况,可以判断内存分配是否合理🎜[xxx@xxx ~]# jmap -heap 15162 Attaching to process ID 15162, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.161-b12 using thread-local object allocation. Mark Sweep Compact GC Heap Configuration: MinHeapFreeRatio = 40 # 最小堆使用比例 MaxHeapFreeRatio = 70 # 最大堆可用比例 MaxHeapSize = 482344960 (460.0MB) # 最大堆空间大小 NewSize = 10485760 (10.0MB) # 新生代分配大小 MaxNewSize = 160759808 (153.3125MB) # 最大新生代可分配大小 OldSize = 20971520 (20.0MB) # 老年代大小 NewRatio = 2 # 新生代比例 SurvivorRatio = 8 # 新生代与 Survivor 比例 MetaspaceSize = 21807104 (20.796875MB) # 元空间大小 CompressedClassSpaceSize = 1073741824 (1024.0MB) # Compressed Class Space 空间大小限制 MaxMetaspaceSize = 17592186044415 MB # 最大元空间大小 G1HeapRegionSize = 0 (0.0MB) # G1 单个 Region 大小 Heap Usage: # 堆使用情况 New Generation (Eden + 1 Survivor Space): # 新生代 capacity = 9502720 (9.0625MB) # 新生代总容量 used = 4995320 (4.763908386230469MB) # 新生代已使用 free = 4507400 (4.298591613769531MB) # 新生代剩余容量 52.56726495150862% used # 新生代使用占比 Eden Space: capacity = 8454144 (8.0625MB) # Eden 区总容量 used = 4029752 (3.8430709838867188MB) # Eden 区已使用 free = 4424392 (4.219429016113281MB) # Eden 区剩余容量 47.665996699370154% used # Eden 区使用占比 From Space: # 其中一个 Survivor 区的内存分布 capacity = 1048576 (1.0MB) used = 965568 (0.92083740234375MB) free = 83008 (0.07916259765625MB) 92.083740234375% used To Space: # 另一个 Survivor 区的内存分布 capacity = 1048576 (1.0MB) used = 0 (0.0MB) free = 1048576 (1.0MB) 0.0% used tenured generation: # 老年代 capacity = 20971520 (20.0MB) used = 10611384 (10.119804382324219MB) free = 10360136 (9.880195617675781MB) 50.599021911621094% used 10730 interned Strings occupying 906232 bytes.Nach dem Login kopierenDarüber hinaus können Sie die ressourcenintensivsten Objekte anzeigen, während die JVM ausgeführt wird,
jmap -histo:live 15162 | mehr
jmap -histo:live 15162 | more
JVM 内存对象列表按照对象所占内存大小排序
instances:实例数 bytes:单位 byte class name:类名 明显看到
CustomObjTest
对象实例以及占用内存过多可惜的是,方案存在局限性,因为它只能排查对象占用内存过高问题
其中 "[" 代表数组,例如 "[C" 代表 Char 数组,"[B" 代表 Byte 数组。如果数组内存占用过多,我们不知道哪些对象持有它,所以就需要 Dump 内存进行离线分析
JVM-Speicherobjektliste wird nach der vom Objekt belegten Speichergröße sortiert
jmap -histo:live
instances: Anzahl der Instanzen bytes: unit byte class name: class name Natürlich siehe
CustomObjTest
Objektinstanz und beansprucht zu viel SpeicherLeider weist die Lösung Einschränkungen auf weil es nur das Problem beheben kann, dass Objekte zu viel Speicher belegenwobei „[“ beispielsweise ein Array darstellt, „[C“ ein Char-Array darstellt und „[B“ ein Byte-Array darstellt. Wenn der Array-Speicher zu viel beansprucht, wissen wir nicht, welche Objekte ihn enthalten, also müssen wir den Speicher für die Offline-Analyse sichern
jmap -histo:live
Führen Sie diesen Befehl aus. Die JVM löst zuerst GC aus und sammelt dann Statistiken Speicherbild des Java-Prozesses, in dem es hauptsächlichSysteminformationen, Eigenschaften der virtuellen Maschine, vollständiger Thread-Dump, Status aller Klassen und Objekte und andere Informationen
Wenn ein Programm einen Speicherüberlauf oder GC hat Ausnahme: Es besteht der Verdacht, dass ein JVM-Speicherleck aufgetreten ist. Dann können wir die Dump-Datei zur Analyse exportieren. Fügen Sie der JVM-Startparameterkonfiguration die folgenden Parameter hinzu
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./(参数为 Dump 文件生成路径) 当 JVM 发生 OOM 异常自动导出 Dump 文件,文件名称默认格式:
java_pid{pid}.hprof
上面配置是在应用抛出 OOM 后自动导出 Dump,或者可以在 JVM 运行时导出 Dump 文件
jmap -dump:file=[文件路径] [pid] # 示例 jmap -dump:file=./jvmdump.hprof 15162Nach dem Login kopieren在本地写一个测试代码,验证下 OOM 以及分析 Dump 文件
设置 VM 参数:-Xms3m -Xmx3m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./ public static void main(String[] args) { List<Object> oomList = Lists.newArrayList(); // 无限循环创建对象 while (true) { oomList.add(new Object()); } }Nach dem Login kopieren通过报错信息得知,
java heap space
表示 OOM 发生在堆区,并生成了 hprof 二进制文件在当前文件夹下JvisualVM 分析
Dump 分析工具有很多,相对而言 JvisualVM、JProfiler、Eclipse Mat,使用人群更多一些。下面以 JvisualVM 举例分析 Dump 文件
列举两个常用的功能,第一个是能看到触发 OOM 的线程堆栈,清晰得知程序溢出的原因
第二个就是可以查看 JVM 内存里保留大小最大的对象,可以自由选择排查个数
点击对象还可以跳转具体的对象引用详情页面
文中 Dump 文件较为简单,而正式环境出错的原因五花八门,所以不对该 Dump 文件做深度解析
注意:JvisualVM 如果分析大 Dump 文件,可能会因为内存不足打不开,需要调整默认的内存
Zusammenfassende Überprüfung
Wenn Sie online auf einen JVM-Speicherüberlauf stoßen, können Sie das Problem mit den folgenden Schritten beheben
jmap -heap
Überprüfen Sie, ob die Speicherzuweisung zu klein istjmap -heap
查看是否内存分配过小jmap -histo
查看是否有明显的对象分配过多且没有释放情况jmap -dump
jmap -dump
Exportieren Sie den aktuellen Speicher-Snapshot der JVM und analysieren Sie den Snapshot mit Tools wie JDK oder MAT. 🎜🎜🎜🎜Wenn das Problem oben nicht lokalisiert werden kann, müssen Sie es überprüfen Ob die Anwendung ständig Ressourcen erstellt, z. B. Netzwerkverbindungen oder Threads, kann dazu führen, dass die Systemressourcen erschöpft werden. 🎜🎜🎜Das obige ist der detaillierte Inhalt vonInterview mit einer bestimmten Gruppe: Wie sollten Sie das Problem beheben, wenn Sie online auf OOM stoßen? Wie kann man es lösen? Welche Optionen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!