Rumah > Java > JavaSoalan temu bual > teks badan

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

Lepaskan: 2023-08-23 14:34:16
ke hadapan
1849 orang telah melayarinya

OOM bermakna terdapat kelemahan dalam program, yang mungkin disebabkan oleh kod atau konfigurasi parameter JVM. Artikel ini bercakap dengan pembaca tentang cara menyelesaikan masalah apabila proses Java mencetuskan OOM.

Ia sering dikatakan kagum dengan persekitaran pengeluaran, dan menyelesaikan masalah dengan cepat juga merupakan tanda kagum

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

Kenapa OOM

OOM bermaksud "Out Of Memory" ingatan sudah habis. Apabila JVM tidak mempunyai memori yang mencukupi untuk memperuntukkan ruang untuk objek, dan pengumpul sampah tidak mempunyai ruang untuk mengitar semula, ia akan membuang ralat ini

Mengapa OOM berlaku secara amnya disebabkan oleh masalah ini

  1. Terlalu sedikit peruntukan : Memori permulaan JVM adalah kecil, dan perniagaan menggunakan banyak memori; atau peruntukan memori dalam kawasan JVM yang berbeza adalah tidak munasabah
  2. Kerentanan kod: objek tertentu sering digunakan, tetapi tidak dikeluarkan selepasnya tidak digunakan lagi, mengakibatkan kehabisan daya ingatan

Memori bocor: Memori yang telah dipohon tidak dilepaskan menyebabkan mesin maya tidak dapat menggunakan memori itu semula . Kerana pemohon tidak lagi digunakan, tetapi mesin maya tidak boleh diperuntukkan kepada orang lain

Memori limpahan: Memori yang digunakan melebihi saiz memori yang boleh diberikan oleh JVM pada masa ini, ia dipanggil limpahan

Kebocoran ingatan berterusan, dan akhirnya ia mesti Akan melimpah, kedua-duanya berkaitan sebab musabab

OOM Biasa

Jenis OOM yang lebih biasa adalah seperti berikut

java.lang.OutOfMemoryErspace Limpahan penjanaan kekal Java7 (kawasan kaedah), yang digunakan untuk menyimpan data seperti maklumat kelas, pemalar, pembolehubah statik dan kod yang disusun oleh pengkompil tepat dalam masa yang telah dimuatkan oleh mesin maya. Setiap kali kelas dimuatkan buat kali pertama, metadata akan disimpan dalam generasi kekal Biasanya ia berlaku dalam sejumlah besar objek Kelas atau halaman JSP, atau ia disebabkan oleh menggunakan teknologi proksi dinamik CgLib.

我们可以通过 - XX:PermSize-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 排查思路

查看 JVM 内存分布

假设我们 Java 应用 PID 为 15162,输入命令查看 JVM 内存分布 jmap -heap 15162

Java8 将永久代变更为元空间,报错:java.lang.OutOfMemoryError: Ruang metadata,元空间内存不足默认进有莌前java.lang.StackOverflowError

虚拟机栈溢出,一般是由于程序中存在 死循环或者深度递归调用度递归调用度递归调用 我家家家置过小也会出现溢出,可以通过 -Xss 设置栈的大小

🎜虚拟机抛出栈溢出错误,可以在日志中定位到错误的类、方法出错误,可以在日志中定位到错误的类、方法space 🎜🎜Jawa 堆内存溢出.工具查看泄漏对象到 GC Roots 的引用链。掌握了泄漏对象的类型信息以及 GC Roots引用链信息,就可以精准地定位出泄漏代码的位置🎜🎜如果不存在内存不存在内存,小歏家确实都还必须存活着,那就应该检查虚拟机的堆参数(-Xmx 与 -Xms) ,查看是否可以将虚拟机的内存调大些🎜🎜小结:方法区和虚拟机栈的溢出从管,下面主要讲解常见的 Java 堆空间的 OOM 排查思路🎜

查看 JVM 内存分布

🎜假设我们 Java 应用 PID 为 15162,输入命令查看 JVM 内存分布1px-style ;wrap-style 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 -timbunan 15162🎜
[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.
Salin selepas log masuk
🎜通过查看 JVM 内存刨制菊行情况,可以判断内存分配是否合理🎜

Selain itu, anda boleh melihat objek yang paling banyak menggunakan sumber semasa JVM sedang berjalan, jmap -histo:live 15162 | morejmap -histo:live 15162 | more

JVM 内存对象列表按照对象所占内存大小排序

  • instances:实例数
  • bytes:单位 byte
  • class name:类名
Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

明显看到 CustomObjTest 对象实例以及占用内存过多

可惜的是,方案存在局限性,因为它只能排查对象占用内存过高问题

其中 "[" 代表数组,例如 "[C" 代表 Char 数组,"[B" 代表 Byte 数组。如果数组内存占用过多,我们不知道哪些对象持有它,所以就需要 Dump 内存进行离线分析

jmap -histo:live

Senarai objek memori JVM diisih mengikut saiz memori yang diduduki oleh objek
  • instance: bilangan instance
  • bait: unit byte
  • nama kelas: nama kelas
Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

Jelas lihatCustomObjTest contoh objek dan mengambil terlalu banyak memoriMalangnya, penyelesaiannya mempunyai batasan kerana ia hanya boleh Menyelesaikan masalah yang objek menduduki terlalu banyak memoridi mana "[" mewakili tatasusunan, contohnya, "[C" mewakili tatasusunan Char dan "[B" mewakili tatasusunan Byte. Jika memori tatasusunan mengambil terlalu banyak, kami tidak tahu objek mana yang memegangnya, jadi kami perlu membuang memori untuk analisis luar talian

jmap -histo:live Laksanakan arahan ini, JVM akan mencetuskan GC dahulu, dan kemudian kumpulkan statistik

Analisis fail buang Fail Dump ialah imej memori proses Java, di mana Ia terutamanya termasuk

maklumat sistem

, sifat mesin maya,

buang benang lengkap

,

status semua kelas dan objek🎜 dan maklumat lain🎜🎜Apabila program mempunyai limpahan memori atau GC pengecualian, disyaki JVM telah berlaku🎜kebocoran memori 🎜, maka kita boleh mengeksport fail Dump untuk analisis🎜🎜Tambah parameter berikut pada konfigurasi parameter permulaan JVM🎜
  • -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 15162
Salin selepas log masuk

在本地写一个测试代码,验证下 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());
    }
}
Salin selepas log masuk

通过报错信息得知,java heap space 表示 OOM 发生在堆区,并生成了 hprof 二进制文件在当前文件夹下

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

JvisualVM 分析

Dump 分析工具有很多,相对而言 JvisualVMJProfilerEclipse Mat,使用人群更多一些。下面以 JvisualVM 举例分析 Dump 文件

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

列举两个常用的功能,第一个是能看到触发 OOM 的线程堆栈,清晰得知程序溢出的原因

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

第二个就是可以查看 JVM 内存里保留大小最大的对象,可以自由选择排查个数

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

点击对象还可以跳转具体的对象引用详情页面

Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?

文中 Dump 文件较为简单,而正式环境出错的原因五花八门,所以不对该 Dump 文件做深度解析

注意:JvisualVM 如果分析大 Dump 文件,可能会因为内存不足打不开,需要调整默认的内存

Semakan ringkasan

Jika anda menghadapi limpahan memori JVM dalam talian, anda boleh menyelesaikan masalah dalam langkah berikut

  1. jmap -heap Semak sama ada peruntukan memori terlalu keciljmap -heap 查看是否内存分配过小
  2. jmap -histo 查看是否有明显的对象分配过多且没有释放情况
  3. jmap -dump
jmap -histo Semak sama ada terdapat apa-apa yang jelas peruntukan objek Terlalu banyak dan tiada pelepasan

jmap -dump Eksport gambar memori semasa JVM dan gunakan alat seperti JDK atau MAT untuk menganalisis syot kilat 🎜🎜🎜🎜Jika masalah tidak dapat ditemui di atas, anda perlu menyemak sama ada aplikasi sentiasa mencipta sumber, seperti rangkaian Sambungan atau benang boleh menyebabkan sumber sistem kehabisan. 🎜🎜🎜

Atas ialah kandungan terperinci Temu bual dengan kumpulan tertentu: Jika anda menemui OOM dalam talian, bagaimanakah anda harus menyelesaikan masalah itu? Bagaimana untuk menyelesaikannya? Apakah pilihan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:Java后端技术全栈
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan