Menangkap Java Thread Dump

1. Ikhtisar

Dalam tutorial ini, kita akan membahas berbagai cara untuk merekam thread dump dari aplikasi Java.

Thread dump adalah cuplikan dari status semua thread dari proses Java . Status setiap utas disajikan dengan pelacakan tumpukan, yang menunjukkan konten tumpukan utas. Thread dump berguna untuk mendiagnosis masalah saat menampilkan aktivitas thread. Thread dump ditulis dalam teks biasa, sehingga kita dapat menyimpan isinya ke file dan melihatnya nanti di editor teks .

Di bagian selanjutnya, kita akan membahas beberapa alat dan pendekatan untuk menghasilkan thread dump.

2. Menggunakan JDK Utilities

JDK menyediakan beberapa utilitas yang dapat menangkap thread dump aplikasi Java. Semua utilitas berada di bawah folder bin di dalam direktori home JDK . Oleh karena itu, kami dapat menjalankan utilitas ini dari baris perintah selama direktori ini berada di jalur sistem kami.

2.1. jstack

jstack adalah utilitas JDK baris perintah yang dapat kita gunakan untuk menangkap thread dump. Ini mengambil pid dari suatu proses dan menampilkan thread dump di konsol. Alternatifnya, kita bisa mengarahkan outputnya ke file.

Mari kita lihat sintaks perintah dasar untuk menangkap thread dump menggunakan jstack:

jstack [-F] [-l] [-m] 

Semua bendera adalah opsional. Mari kita lihat apa artinya:

  • Opsi -F memaksa pembuangan benang; berguna untuk digunakan ketika jstack pid tidak merespons (proses macet)
  • Opsi -l menginstruksikan utilitas untuk mencari sinkronisasi yang dapat dimiliki di heap dan kunci
  • Opsi -m mencetak bingkai tumpukan asli (C & C ++) selain bingkai tumpukan Java

Mari kita gunakan pengetahuan ini untuk digunakan dengan menangkap thread dump dan mengarahkan hasilnya ke file:

jstack 17264 > /tmp/threaddump.txt

Ingatlah bahwa kita bisa dengan mudah mendapatkan pid dari proses Java dengan menggunakan perintah jps .

2.2. Kontrol Misi Jawa

Java Mission Control (JMC) adalah alat GUI yang mengumpulkan dan menganalisis data dari aplikasi Java. Setelah kami meluncurkan JMC, ini akan menampilkan daftar proses Java yang berjalan di mesin lokal. Kami juga dapat terhubung ke proses Java jarak jauh melalui JMC.

Kita dapat mengklik kanan pada proses tersebut dan mengklik opsi " Mulai Perekaman Penerbangan ". Setelah ini, tab Threads menampilkan Thread Dumps:

2.3. jvisualvm.dll

jvisualvm adalah alat dengan antarmuka pengguna grafis yang memungkinkan kita memantau, memecahkan masalah, dan membuat profil aplikasi Java . GUI-nya sederhana tetapi sangat intuitif dan mudah digunakan.

Salah satu dari banyak opsinya memungkinkan kita menangkap thread dump. Jika kita mengklik kanan pada proses Java dan memilih opsi "Thread Dump" , alat tersebut akan membuat thread dump dan membukanya di tab baru:

Mulai JDK 9, Visual VM tidak termasuk dalam distribusi Oracle JDK dan Open JDK. Oleh karena itu, jika kita menggunakan Java 9 atau versi yang lebih baru, kita bisa mendapatkan JVisualVM dari situs proyek sumber terbuka Visual VM.

2.4. jcmd

jcmd adalah alat yang bekerja dengan mengirimkan permintaan perintah ke JVM. Meskipun kuat, itu tidak berisi fungsionalitas jarak jauh - kita harus menggunakannya di mesin yang sama tempat proses Java berjalan.

Salah satu dari banyak perintahnya adalah Thread.print . Kita bisa menggunakannya untuk mendapatkan thread dump hanya dengan menentukan pid dari proses tersebut:

jcmd 17264 Thread.print

2.5. jconsole

jconsole memungkinkan kita memeriksa jejak tumpukan setiap utas. Jika kita membuka jconsole dan terhubung ke proses Java yang sedang berjalan, kita dapat menavigasi ke tab Threads dan menemukan jejak tumpukan setiap thread :

2.6. Ringkasan

Ternyata, ada banyak cara untuk menangkap thread dump menggunakan utilitas JDK. Mari luangkan waktu sejenak untuk merenungkan masing-masing dan menguraikan pro dan kontra mereka:

  • jstack : menyediakan cara tercepat dan termudah untuk merekam thread dump. Namun, alternatif yang lebih baik tersedia mulai dengan Java 8
  • jmc: enhanced JDK profiling and diagnostics tool. It minimizes the performance overhead that's usually an issue with profiling tools
  • jvisualvm: lightweight and open-source profiling tool with an excellent GUI console
  • jcmd: extremely powerful and recommended for Java 8 and later. A single tool that serves many purposes – capturing thread dump (jstack), heap dump (jmap), system properties and command-line arguments (jinfo)
  • jconsole: let's us inspect thread stack trace information

3. From the Command Line

In enterprise application servers, only the JRE is installed for security reasons. Thus, we can not use the above-mentioned utilities as they are part of JDK. However, there are various command-line alternatives that let us capture thread dumps easily.

3.1. kill -3 Command (Linux/Unix)

The easiest way to capture a thread dump in Unix-like systems is through the kill command, which we can use to send a signal to a process using the kill() system call. In this use case, we'll send it the -3 signal.

Using our same pid from earlier examples, let's take a look at how to use kill to capture a thread dump:

kill -3 17264

This way the signal-receiving Java process will print the thread dump on the standard output.

If we run the Java process with the following combination of tuning flags, then it will also redirect the thread dump to the given file:

-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=~/jvm.log

Now if we send the -3 signal, in addition to the standard output, the dump will be available at ~/jvm.log file.

3.2. Ctrl + Break (Windows)

In Windows operating systems, we can capture a thread dump using the CTRL and Break key combination. To take a thread dump, navigate to the console used to launch the Java application and press CTRL and Break keys together.

It's worth noting that, on some keyboards, the Break key is not available. Therefore, in such cases, a thread dump can be captured using CTRL, SHIFT, and Pause keys together.

Both of these commands print the thread dump to the console.

4. Programmatically Using ThreadMxBean

The last approach we will discuss in the article is using JMX. We'll use ThreadMxBean to capture the thread dump. Let's see it in code:

private static String threadDump(boolean lockedMonitors, boolean lockedSynchronizers) { StringBuffer threadDump = new StringBuffer(System.lineSeparator()); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); for(ThreadInfo threadInfo : threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { threadDump.append(threadInfo.toString()); } return threadDump.toString(); }

In the above program, we are performing several steps:

  1. At first, an empty StringBuffer is initialized to hold the stack information of each thread.
  2. We then use the ManagementFactory class to get the instance of ThreadMxBean. A ManagementFactory is a factory class for getting managed beans for the Java platform. In addition, a ThreadMxBean is the management interface for the thread system of the JVM.
  3. Setting lockedMonitors and lockedSynchronizers values to true indicates to capture the ownable synchronizers and all locked monitors in the thread dump.

5. Conclusion

In this article, we've shown multiple ways to capture a thread dump.

At first, we discussed various JDK Utilities and then the command-line alternatives. In the last section, we concluded with the programmatic approach using JMX.

Seperti biasa, kode sumber lengkap dari contoh ini tersedia di GitHub.