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:

AlatPeranBab khusus
jpsdaftar proses JVM berjalan beserta PID—
jstatsampling statistik GC dan generasi secara berulang—
jcmdperintah serba-bisa ke JVM: flag, heap, threadjcmd, jstack, dan jmap
jstackthread dump dan deteksi deadlockjcmd, jstack, dan jmap
jmaphistogram objek dan heap dumpjcmd, 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:

bash Mendaftar proses JVM
jps -l
text Keluaran di mesin uji saat program uji berjalan
23228 jdk.jcmd/sun.tools.jps.Jps
23214 GelombangPanjang

Dua 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:

KolomArti
S0, S1pemakaian dua survivor space (%)
Epemakaian Eden (%)
Opemakaian old generation (%)
M, CCSpemakaian Metaspace dan compressed class space (%)
YGC, YGCTjumlah dan total waktu young GC
FGC, FGCTjumlah dan total waktu full GC
GCTtotal 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:

bash Sampling dua kali dengan jeda 5 detik
jstat -gcutil 23407
jstat -gcutil 23407
text Keluaran di mesin uji (nilai bervariasi)
  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.026

Pembacaan 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:

text
putaran 1 selesai
putaran 2 selesai
putaran 3 selesai
putaran 4 selesai
putaran 5 selesai
total tertahan: 5 blok

Mari kita telaah perilakunya:

  1. Baris 9 (new byte[8 * 1024 * 1024]): tiap putaran mengalokasikan 8 MB di Eden — pada heap kecil, beberapa putaran saja memicu minor GC beruntun.
  2. 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 kolom O jstat bergerak.
  3. Baris 13 (Thread.sleep(300)): jeda 300 ms memberi waktu jstat menangkap 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 #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

AlokasiBergelombang.java

Unduh berkas
java
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");
    }
}