1. Pengenalan
Dalam artikel ini, kami akan menunjukkan cara yang berbeza untuk menangkap timbunan timbunan di Java.
Tumpukan timbunan adalah gambar semua objek yang ada dalam memori di JVM pada waktu tertentu . Mereka sangat berguna untuk menyelesaikan masalah kebocoran memori dan mengoptimumkan penggunaan memori dalam aplikasi Java.
Tumpukan timbunan biasanya disimpan dalam fail hprof format binari. Kita boleh membuka dan menganalisis fail ini menggunakan alat seperti jhat atau JVisualVM. Juga, bagi pengguna Eclipse sangat biasa menggunakan MAT.
Pada bahagian seterusnya, kami akan melalui pelbagai alat dan pendekatan untuk menghasilkan timbunan timbunan dan kami akan menunjukkan perbezaan utama di antara mereka.
2. Alat JDK
JDK dilengkapi dengan beberapa alat untuk menangkap timbunan timbunan dengan cara yang berbeza. Semua alat ini terletak di bawah folder tong sampah di dalam direktori utama JDK . Oleh itu, kita boleh memulakannya dari baris arahan selagi direktori ini disertakan dalam jalur sistem.
Di bahagian seterusnya, kami akan menunjukkan cara menggunakan alat ini untuk menangkap timbunan timbunan.
2.1. jmap
jmap adalah alat untuk mencetak statistik mengenai memori dalam JVM yang sedang berjalan. Kita boleh menggunakannya untuk proses tempatan atau jarak jauh.
Untuk menangkap timbunan timbunan menggunakan jmap, kita perlu menggunakan pilihan pembuangan :
jmap -dump:[live],format=b,file=
Bersama dengan pilihan itu, kita harus menentukan beberapa parameter:
- live : jika diatur hanya mencetak objek yang mempunyai rujukan aktif dan membuang objek yang siap dikumpulkan sampah. Parameter ini adalah pilihan
- format = b : menentukan bahawa fail pembuangan akan dalam format binari. Sekiranya tidak ditetapkan hasilnya sama
- file : fail tempat pembuangan akan ditulis
- pid : id proses Java
Contohnya seperti ini:
jmap -dump:live,format=b,file=/tmp/dump.hprof 12587
Ingatlah bahawa kita boleh mendapatkan pid daripada proses Java dengan menggunakan jps arahan.
Perlu diingat bahawa jmap diperkenalkan di JDK sebagai alat eksperimen dan tidak disokong. Oleh itu, dalam beberapa kes, lebih baik menggunakan alat lain sebagai gantinya.
2.2. jcmd
jcmd adalah alat yang sangat lengkap yang berfungsi dengan menghantar permintaan perintah ke JVM. Kita harus menggunakannya di mesin yang sama dengan proses Java berjalan.
Salah satu daripada banyak perintahnya adalah GC.heap_dump . Kita boleh menggunakannya untuk mendapat tempat pembuangan timbunan hanya dengan menentukan pid proses dan laluan fail output:
jcmd GC.heap_dump
Kita dapat melaksanakannya dengan parameter yang sama seperti yang kita gunakan sebelumnya:
jcmd 12587 GC.heap_dump /tmp/dump.hprof
Seperti jmap, dump yang dihasilkan adalah dalam format binari.
2.3. JVisualVM
JVisualVM adalah alat dengan antara muka pengguna grafik yang memungkinkan kita memantau, menyelesaikan masalah, dan profil aplikasi Java . GUI ringkas tetapi sangat intuitif dan mudah digunakan.
Salah satu daripada banyak pilihannya membolehkan kita menangkap timbunan timbunan. Jika kita klik kanan pada proses Java dan memilih opsi "Heap Dump" , alat akan membuat timbunan timbunan dan membukanya di tab baru:

Perhatikan bahawa kita dapat menemukan jalan file yang dibuat di bahagian "Maklumat Asas" .
Bermula dari JDK 9, Visual VM tidak termasuk dalam edaran Oracle JDK dan Open JDK. Oleh itu, jika kita menggunakan Java 9 atau versi yang lebih baru, kita dapat memperoleh JVisualVM dari laman projek sumber terbuka Visual VM.
3. Tangkap Tumpukan Tumpukan Secara Automatik
Semua alat yang telah kami tunjukkan di bahagian sebelumnya bertujuan untuk menangkap timbunan timbunan secara manual pada waktu tertentu. Dalam beberapa kes, kami ingin mendapatkan timbunan timbunan apabila berlakunya java.lang.OutOfMemoryError sehingga membantu kami menyiasat ralat.
Untuk kes-kes ini, Java menyediakan pilihan baris arahan HeapDumpOnOutOfMemoryError yang menghasilkan timbunan timbunan apabila java.lang.OutOfMemoryError dilemparkan:
java -XX:+HeapDumpOnOutOfMemoryError
Secara lalai, ia menyimpan dump dalam fail java_pid.hprof dalam direktori tempat kami menjalankan aplikasi. Sekiranya kita ingin menentukan fail atau direktori lain, kita dapat menetapkannya dalam pilihan HeapDumpPath :
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=
Apabila aplikasi kita kehabisan memori menggunakan pilihan ini, kita akan dapat melihat di dalam log fail yang dibuat yang mengandungi timbunan timbunan:
java.lang.OutOfMemoryError: Requested array size exceeds VM limit Dumping heap to java_pid12587.hprof ... Exception in thread "main" Heap dump file created [4744371 bytes in 0.029 secs] java.lang.OutOfMemoryError: Requested array size exceeds VM limit at com.baeldung.heapdump.App.main(App.java:7)
Dalam contoh di atas, ia ditulis ke fail java_pid12587.hprof .
Seperti yang kita lihat, pilihan ini sangat berguna dan tidak ada overhead ketika menjalankan aplikasi dengan pilihan ini. Oleh itu, sangat digalakkan untuk menggunakan pilihan ini selalu, terutamanya dalam pengeluaran.
Akhirnya, pilihan ini juga dapat ditentukan semasa menjalankan dengan menggunakan HotSpotDiagnostic MBean . Untuk melakukannya, kita boleh menggunakan JConsole dan menetapkan pilihan HeapDumpOnOutOfMemoryError VM ke true :

Kami boleh mendapatkan lebih banyak maklumat mengenai MBeans dan JMX dalam artikel ini.
4. JMX
The last approach that we'll cover in this article is using JMX. We'll use the HotSpotDiagnostic MBean that we briefly introduced in the previous section. This MBean provides a dumpHeap method that accepts 2 parameters:
- outputFile: the path of the file for the dump. The file should have the hprof extension
- live: if set to true it dumps only the active objects in memory, as we've seen with jmap before
In the next sections, we'll show 2 different ways to invoke this method in order to capture a heap dump.
4.1. JConsole
The easiest way to use the HotSpotDiagnostic MBean is by using a JMX client such as JConsole.
If we open JConsole and connect to a running Java process, we can navigate to the MBeans tab and find the HotSpotDiagnostic under com.sun.management. In operations, we can find the dumpHeap method that we've described before:

As shown, we just need to introduce the parameters outputFile and live into the p0 and p1 text fields in order to perform the dumpHeap operation.
4.2. Programmatic Way
The other way to use the HotSpotDiagnostic MBean is by invoking it programmatically from Java code.
To do so, we first need to get an MBeanServer instance in order to get an MBean that is registered in the application. After that, we simply need to get an instance of a HotSpotDiagnosticMXBean and call its dumpHeap method.
Let's see it in code:
public static void dumpHeap(String filePath, boolean live) throws IOException { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy( server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); mxBean.dumpHeap(filePath, live); }
Notice that an hprof file cannot be overwritten. Therefore, we should take this into account when creating an application that prints heap dumps. If we fail to do so we'll get an exception:
Exception in thread "main" java.io.IOException: File exists at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method) at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)
5. Conclusion
In this tutorial, we've shown multiple ways to capture a heap dump in Java.
Sebagai aturan praktis, kita harus ingat untuk menggunakan pilihan HeapDumpOnOutOfMemoryError selalu ketika menjalankan aplikasi Java. Untuk tujuan lain, mana-mana alat lain dapat digunakan dengan sempurna selagi kita ingat status jmap yang tidak disokong.
Seperti biasa, kod sumber penuh contoh terdapat di GitHub.