Aplikasi Kotlin/JVM yang berjalan di produksi jarang memakai pengaturan default JVM. Sebagian besar beban kerja nyata memerlukan penyesuaian ukuran heap, pemilihan kolektor GC, dan pengaturan cadangan saat terjadi galat memori. Pengaturan ini diberikan lewat baris perintah java dalam bentuk flag yang diawali -X (ukuran) atau -XX (opsi extended). Pada chapter ini kita akan membahas flag yang paling sering dipakai, cara memverifikasinya di runtime, serta rekomendasi praktis untuk tipe aplikasi yang berbeda.
Kategori Flag #
Flag JVM dikelompokkan menjadi tiga kategori berdasarkan stabilitasnya:
| Kategori | Prefiks | Stabilitas | Contoh |
|---|---|---|---|
| Standard | - | Stabil lintas versi | -cp, -jar, -Dprop=val |
| Non-standard | -X | Stabil dalam satu vendor | -Xmx, -Xms, -Xss |
| Developer | -XX | Bisa berubah antar versi | -XX:+UseG1GC, -XX:MaxGCPauseMillis=100 |
Flag -XX dapat berbentuk boolean (-XX:+Name / -XX:-Name) atau key-value (-XX:Key=Value).
Mengatur Ukuran Heap #
Dua flag yang paling sering dijumpai mengatur heap:
-Xms<size>: ukuran heap awal saat JVM start. Jika disetel tinggi, JVM tidak perlu tumbuh bertahap.-Xmx<size>: ukuran heap maksimum. Melebihi batas ini memicuOutOfMemoryError: Java heap space.
Ukuran ditulis dengan suffix k, m, atau g (kilobyte, megabyte, gigabyte). Contoh: -Xmx2g berarti maksimum 2 gigabyte.
# Heap awal 512 MB, maksimum 2 GB, dengan GC ZGC
java -Xms512m -Xmx2g -XX:+UseZGC -jar aplikasi.jar
# Heap besar untuk batch processing
java -Xmx8g -XX:+UseParallelGC -jar batch.jarMemilih Garbage Collector #
Pilihan GC memengaruhi tradeoff throughput dan latensi. Empat kolektor utama yang dapat dipakai di JVM modern:
| Flag | Kolektor | Karakter | Cocok untuk |
|---|---|---|---|
-XX:+UseSerialGC | Serial | Single-thread, heap kecil | CLI tools, container kecil |
-XX:+UseParallelGC | Parallel | Throughput-oriented, multi-thread | Batch processing, ETL |
-XX:+UseG1GC | G1 (default JDK 9+) | Region-based, target pause | Server umum, REST API |
-XX:+UseZGC | ZGC | Sub-millisecond pause | Latency-critical, realtime |
-XX:+UseShenandoahGC | Shenandoah | Concurrent evacuation | Latency-critical, heap besar |
G1 menerima flag target pause -XX:MaxGCPauseMillis=<ms> (default 200). JVM akan menyesuaikan ukuran region untuk mendekati target, namun target bukan jaminan keras.
Heap Dump saat OOM #
Saat aplikasi kehabisan memori, logika bisnis biasanya rusak parah. Salah satu langkah pertama dalam investigasi adalah mendapatkan heap dump pada momen tepat sebelum proses berhenti. Flag berikut mengaktifkannya:
java -Xmx1g \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/app/heapdump.hprof \
-jar aplikasi.jarSaat OutOfMemoryError terpicu, JVM otomatis menulis heap dump ke path yang ditentukan. File .hprof kemudian dibuka dengan Eclipse MAT atau VisualVM untuk analisis retained size dan path to GC roots.
Inspeksi Flag Aktif di Runtime #
Kita dapat membaca properti sistem dan konfigurasi runtime lewat API Java. Kode berikut memperlihatkan properti JVM yang relevan dan daftar flag penting untuk referensi cepat.
fun main() {
println("=== Properti JVM yang Relevan untuk Konfigurasi ===")
// Properti sistem dapat dibaca di runtime untuk verifikasi flag yang aktif
listOf(
"java.version" to "Versi Java",
"java.vm.name" to "Nama JVM",
"java.vm.info" to "Info JVM",
"java.specification.version" to "Spec Java",
"os.arch" to "Arsitektur OS",
"file.encoding" to "Encoding default"
).forEach { (key, label) ->
println(" $label ($key): ${System.getProperty(key)}")
}
println()
println("=== Flag Penting untuk Aplikasi Produksi ===")
println(" -Xms<size> : ukuran heap awal (initial)")
println(" -Xmx<size> : ukuran heap maksimum")
println(" -XX:+UseG1GC : pakai kolektor G1 (default sejak JDK 9)")
println(" -XX:+UseZGC : pakai kolektor ZGC (low-latency)")
println(" -XX:+UseShenandoahGC : pakai kolektor Shenandoah (concurrent)")
println(" -XX:MaxGCPauseMillis : target pause time G1 (default 200 ms)")
println(" -XX:+HeapDumpOnOutOfMemoryError : dump heap saat OOM")
println(" -XX:HeapDumpPath=<path> : lokasi file heap dump")
println(" -Xss<size> : ukuran thread stack")
println(" -XX:+UseStringDeduplication : dedup string di heap (G1)")
println()
println("=== Contoh Baris Perintah ===")
println(" java -Xms512m -Xmx2g -XX:+UseZGC -jar app.jar")
println(" java -Xmx4g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump.hprof -jar app.jar")
}Output yang Dihasilkan:
=== Properti JVM yang Relevan untuk Konfigurasi ===
Versi Java (java.version): 21.0.12.1
Nama JVM (java.vm.name): OpenJDK 64-Bit Server VM
Info JVM (java.vm.info): mixed mode, sharing
Spec Java (java.specification.version): 21
Arsitektur OS (os.arch): amd64
Encoding default (file.encoding): UTF-8
=== Flag Penting untuk Aplikasi Produksi ===
-Xms<size> : ukuran heap awal (initial)
-Xmx<size> : ukuran heap maksimum
-XX:+UseG1GC : pakai kolektor G1 (default sejak JDK 9)
-XX:+UseZGC : pakai kolektor ZGC (low-latency)
-XX:+UseShenandoahGC : pakai kolektor Shenandoah (concurrent)
-XX:MaxGCPauseMillis : target pause time G1 (default 200 ms)
-XX:+HeapDumpOnOutOfMemoryError : dump heap saat OOM
-XX:HeapDumpPath=<path> : lokasi file heap dump
-Xss<size> : ukuran thread stack
-XX:+UseStringDeduplication : dedup string di heap (G1)
=== Contoh Baris Perintah ===
java -Xms512m -Xmx2g -XX:+UseZGC -jar app.jar
java -Xmx4g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump.hprof -jar app.jarMari kita telaah kode di atas:
System.getProperty(key): API standar Java yang membaca properti sistem yang ditetapkan saat startup (-Dprop=value) atau bawaan JVM. Kita memakainya untuk memverifikasi versi JVM dan encoding tanpa menjalankanjava -versionterpisah.- Daftar properti: setiap pasangan
(key, label)dicetak dengan format yang konsisten. PolaPair+forEachini menghindari duplikasiprintlnuntuk setiap properti. - Daftar flag: ditampilkan sebagai cheat sheet di output program. Pembaca dapat membandingkan dengan daftar pada dokumentasi resmi Oracle atau OpenJDK untuk verifikasi.
Verifikasi Flag Aktif #
Selain membaca System.getProperty, JVM menyediakan dua mekanisme untuk memverifikasi flag mana yang aktif:
# Menampilkan semua flag -XX dan nilainya
java -XX:+PrintFlagsFinal -version | head -20
# Untuk flag tertentu (sejak JDK 9)
jcmd <PID> VM.flags
# Mencatat GC flags ke stdout saat startup
java -Xlog:gc*=info -jar aplikasi.jarReferensi Lanjutan #
- JVM Guide
— panduan resmi HotSpot JVM Java SE 21 untuk opsi
-X,-XX, dan flags GC - Java SE 21 Thread
— dokumentasi
java.lang.ThreadJava SE 21 untuk opsi ukuran stack thread
Penutup #
Pemilihan flag JVM yang tepat memengaruhi performa dan stabilitas aplikasi secara signifikan. Setel -Xms dan -Xmx sesuai profil memori, pilih kolektor GC berdasarkan tradeoff throughput/latensi, dan selalu aktifkan -XX:+HeapDumpOnOutOfMemoryError di produksi. Pada chapter berikutnya kita akan membahas alat profiling yang memanfaatkan konfigurasi ini untuk memberi visibilitas ke dalam runtime.