Aplikasi di mesin pengembang dan di produksi sama-sama menjalankan JVM, tetapi produksi tidak memberi kita debugger yang menyapa. Yang tersedia adalah barisan alat kecil di folder bin JDK yang mengintip JVM hidup dari luar — tanpa menghentikannya, tanpa mengubah satu baris kode. Merekam kondisi memori sebelum masalah terjadi adalah pembeda antara tim yang menebak dan tim yang tahu. Pada chapter ini kita kenalan dengan perangkat dasarnya: jps untuk menemukan proses, jstat untuk sampling memori berulang, dan jconsole untuk intipan visual — sementara jcmd dan JFR yang lebih kuat masing-masing mendapat chapter sendiri setelah ini.
Jaring Alat di Folder bin #
Lima alat CLI menutup mayoritas kebutuhan observability harian:
| Alat | Peran | Bab khusus |
|---|---|---|
jps | daftar proses JVM berjalan beserta PID | — |
jstat | sampling statistik GC dan generasi secara berulang | — |
jcmd | perintah serba-bisa ke JVM: flag, heap, thread | jcmd, jstack, dan jmap |
jstack | thread dump dan deteksi deadlock | jcmd, jstack, dan jmap |
jmap | histogram objek dan heap dump | jcmd, jstack, dan jmap |
Semua alat bekerja dengan mekanisme attach: alat memasang diri ke JVM tujuan lewat PID, JVM menyediakan jalur komunikasi khusus, lalu data dikirim tanpa mengganggu thread aplikasi. Mekanisme inilah yang membuat observability “hangat” — data yang dilihat adalah kondisi saat itu juga.
jps: Menemukan Proses Sasaran #
Langkah pertama setiap penyelidikan adalah menjawab: proses Java mana yang berjalan? Perintah jps -l mendaftar seluruh JVM milik user saat ini, lengkap dengan nama class utamanya:
jps -l23228 jdk.jcmd/sun.tools.jps.Jps
23214 GelombangPanjangDua baris itu memuat pelajaran kecil: baris kedua adalah program uji kita — PID 23214 pasti berbeda di setiap eksekusi, karena PID diberikan sistem operasi. Baris pertama menunjukkan jps ikut terlihat — alat itu sendiri adalah program Java, dan -l menampilkan nama modulnya. Angka PID inilah tiket masuk bagi semua alat berikutnya: jstat 23214, jcmd 23214, dan seterusnya.
jstat: Sampling Memori dari Luar #
jstat -gcutil <pid> mencetak persentase pemakaian tiap generasi plus penghitung GC, dan bila diberi interval ia menjadi deret waktu: jstat -gcutil <pid> 1000 mengambil sampel tiap detik. Kolom-kolomnya:
| Kolom | Arti |
|---|---|
S0, S1 | pemakaian dua survivor space (%) |
E | pemakaian Eden (%) |
O | pemakaian old generation (%) |
M, CCS | pemakaian Metaspace dan compressed class space (%) |
YGC, YGCT | jumlah dan total waktu young GC |
FGC, FGCT | jumlah dan total waktu full GC |
GCT | total waktu seluruh GC |
Kekuatan jstat terlihat saat dua sampel dibandingkan. Berikut hasil sungguhan pada program uji yang mengalokasikan gelombang objek sambil mempertahankan sebagiannya, dijalankan dengan Serial GC dan heap 128 MB:
jstat -gcutil 23407
jstat -gcutil 23407 S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT
3.71 0.00 0.00 77.63 26.54 4.68 10 0.011 0 0.000 - - 0.011
S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT
0.00 0.00 0.00 95.13 26.54 4.68 20 0.024 1 0.002 - - 0.026Pembacaan dua sampel ini adalah inti diagnosis: kolom O merangkak dari 77% ke 95% — old generation terus terisi objek penyintas, dan FGC yang semula 0 menjadi 1: full GC pertama terpaksa berjalan. Pola O yang hanya naik tanpa pernah turun berarti objek berumur panjang menumpuk — ciri kebocoran sebagaimana dibahas Chapter Memory Leaks. Semua angka tentu berbeda pada eksekusi lain; yang stabil adalah makna kolomnya.
Program Sasaran untuk Latihan #
Menguji alat monitoring membutuhkan sasaran yang berprilaku terlihat. Program berikut mengalokasikan gelombang memori berturut-turut sambil menahan sebagian blok agar terjadi promosi ke old generation — hidup dalam waktu cukup untuk diamati:
import java.util.ArrayList;
import java.util.List;
public class AlokasiBergelombang {
public static void main(String[] args) throws Exception {
List<byte[]> bertahan = new ArrayList<>();
for (int putaran = 1; putaran <= 5; putaran++) {
byte[] gelombang = new byte[8 * 1024 * 1024]; // 8 MB per putaran
gelombang[0] = (byte) putaran;
bertahan.add(gelombang); // sebagian objek sengaja dijadikan penyintas
System.out.println("putaran " + putaran + " selesai");
Thread.sleep(300);
}
System.out.println("total tertahan: " + bertahan.size() + " blok");
}
}Output yang Dihasilkan:
putaran 1 selesai
putaran 2 selesai
putaran 3 selesai
putaran 4 selesai
putaran 5 selesai
total tertahan: 5 blokMari kita telaah perilakunya:
- Baris 9 (
new byte[8 * 1024 * 1024]): tiap putaran mengalokasikan 8 MB di Eden — pada heap kecil, beberapa putaran saja memicu minor GC beruntun. - Baris 11 (
bertahan.add(gelombang)): menyimpan referensi di koleksi berarti objek menyintas koleksi dan, sebagaimana dibahas Chapter Object Lifecycle, kandidat dipromosikan ke old generation — persis yang membuat kolomOjstat bergerak. - Baris 13 (
Thread.sleep(300)): jeda 300 ms memberi waktujstatmenangkap beberapa sampel sebelum program selesai. Saat berlatih, naikkan jumlah putaran dan durasi jeda agar jendela observasinya lebih lebar.
Cara berlatihnya: jalankan program ini (atau versi berputaran lebih banyak), buka terminal kedua, ambil PID dengan jps -l, lalu pantau dengan jstat -gcutil <pid> 1000 sambil menonton kolom E naik-turun tiap minor GC dan O menanjak perlahan.
jconsole dan JMC untuk Intipan Visual #
Data teks cepat habis dimakna ketika yang dibutuhkan adalah tren. jconsole — satu-satunya alat GUI yang ikut terpasang bersama JDK — menampilkan grafik live penggunaan heap, thread, dan class loading dari JVM yang dipilih lewat dialog sambungan. Untuk pembelajaran dan pemeriksaan singkat di mesin lokal, grafik naik-turun heap-nya sudah menjawab banyak pertanyaan.
Kebutuhan produksi yang lebih berat berpindah ke JDK Mission Control (JMC) — klien analisis untuk rekaman JFR dengan tampilan dashboard, flame graph, dan pembacaan event otomatis. JMC terpasang terpisah dari JDK, dan cara kerjanya — merekam profil jangka panjang dengan overhead di bawah 1% — adalah pokok chapter berikutnya. Urutan alat yang sehat: jps menemukan target, jstat/jcmd memberi gambaran cepat, JFR merekam untuk analisis mendalam di JMC.
Dengan jps dan jstat di tangan, fondasi monitoring berdiri. Tiga alat berikutnya menempati kotak alat diagnosis yang lebih dalam — jcmd, jstack, dan jmap — dan masing-masing kita bawa keluar dari bengkelnya pada Chapter jcmd, jstack, dan jmap.
Referensi #
- Oracle: jps Tool Reference (JDK 25)
- Oracle: jstat Tool Reference (JDK 25)
- Oracle: jconsole Tool Reference (JDK 25)
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
AlokasiBergelombang.java
Unduh berkasimport java.util.ArrayList;
import java.util.List;
public class AlokasiBergelombang {
public static void main(String[] args) throws Exception {
List<byte[]> bertahan = new ArrayList<>();
for (int putaran = 1; putaran <= 5; putaran++) {
byte[] gelombang = new byte[8 * 1024 * 1024]; // 8 MB per putaran
gelombang[0] = (byte) putaran;
bertahan.add(gelombang); // sebagian objek sengaja dijadikan penyintas
System.out.println("putaran " + putaran + " selesai");
Thread.sleep(300);
}
System.out.println("total tertahan: " + bertahan.size() + " blok");
}
}