Skip to content

JVM Performance Monitoring Tools

6 min read

Command-Line Tools

The JDK ships with a suite of command-line tools located in $JAVA_HOME/bin/, serving as the first line of defense for JVM monitoring and diagnostics.

jps — List Java Processes

# List all Java processes
jps

# Output full main class name
jps -l

# Output JVM arguments
jps -v

# Output main method arguments
jps -m
12345 org.example.MyApp
12346 sun.tools.jps.Jps

jstat — Monitor GC Statistics

jstat is the most commonly used command-line tool for monitoring GC, providing continuous observation of memory and GC behavior.

# View GC summary (refresh every 1 second, 10 times)
jstat -gc <pid> 1000 10

# View GC summary (with percentage for each generation)
jstat -gcutil <pid> 1000 10

# View young generation GC statistics
jstat -gcnew <pid>

# View old generation GC statistics
jstat -gcold <pid>

# View GC causes
jstat -gccause <pid>

jstat -gc output field reference:

Column Meaning
S0C/S1C Survivor 0/1 capacity (KB)
S0U/S1U Survivor 0/1 used (KB)
EC/EU Eden capacity/used (KB)
OC/OU Old generation capacity/used (KB)
MC/MU Metaspace capacity/used (KB)
YGC/FGC Young GC / Full GC count
YGCT/FGCT Young GC / Full GC total time (seconds)
GCT Total GC time (seconds)
# Practical example: calculate GC pause percentage
jstat -gcutil <pid> 1000 5
# Observe the increment in YGCT and FGCT, divide by the sampling interval to get GC pause percentage

jinfo — View/Modify JVM Parameters

# View all JVM parameters
jinfo <pid>

# View a specific parameter
jinfo -flag MaxHeapSize <pid>
jinfo -flag UseG1GC <pid>

# Dynamically modify parameters (only for writeable flags)
jinfo -flag +PrintGCDetails <pid>
jinfo -flag -PrintGCDetails <pid>

# View system properties
jinfo -sysprops <pid>

jmap — Memory Mapping and Heap Dumps

# View heap memory summary
jmap -heap <pid>

# View object statistics (grouped by class, sorted by size)
jmap -histo <pid> | head -20

# View only live objects (triggers Full GC)
jmap -histo:live <pid> | head -20

# Export heap dump
jmap -dump:format=b,file=heap.hprof <pid>

# Export heap dump of live objects only (triggers Full GC)
jmap -dump:live,format=b,file=heap.hprof <pid>

# View objects waiting for finalization
jmap -finalizerinfo <pid>

jmap -histo output example:

 num     #instances         #bytes  class name
   1:       1234567      123456789  [B (byte arrays)
   2:        567890       45678901  java.lang.String
   3:        345678       23456789  java.util.HashMap$Node
   4:        234567       12345678  java.lang.Object

Note: Some jmap functionality is replaced by jcmd in JDK 9+. In production environments, jmap -histo:live triggers Full GC — use with caution.

jstack — Thread Stack Dump

# Print thread stacks
jstack <pid>

# Force print (when process is unresponsive)
jstack -F <pid>

# Print lock information
jstack -l <pid>

# Output to file
jstack <pid> > thread_dump.txt

Thread state reference:

State Meaning
RUNNABLE Running or waiting for CPU
BLOCKED Waiting to acquire a monitor lock
WAITING Waiting indefinitely (Object.wait/Join/LockSupport.park)
TIMED_WAITING Waiting with timeout (sleep/wait(timeout)/parkNanos)
TERMINATED Has exited

Deadlock detection: jstack reports detected deadlocks at the end of its output.

jcmd — Multi-Function Command

jcmd is a unified command-line tool introduced in JDK 7+, consolidating functionality from jps, jinfo, jmap, and jstack:

# List Java processes
jcmd

# View all commands supported by a process
jcmd <pid> help

# Thread stack (replaces jstack)
jcmd <pid> Thread.print

# Heap info (replaces jmap -heap)
jcmd <pid> GC.heap_info

# Object statistics (replaces jmap -histo)
jcmd <pid> GC.class_histogram

# Heap dump (replaces jmap -dump)
jcmd <pid> GC.heap_dump filename=heap.hprof

# View JVM parameters
jcmd <pid> VM.flags
jcmd <pid> VM.command_line

# View JVM system properties
jcmd <pid> VM.system_properties

# JFR-related commands
jcmd <pid> JFR.start
jcmd <pid> JFR.dump filename=recording.jfr
jcmd <pid> JFR.stop

Graphical Tools

VisualVM

VisualVM is a full-featured monitoring tool bundled with JDK 6-8 or available as a standalone download for JDK 9+.

Core features:

  • Overview: Process basic info, JVM parameters, system properties
  • Monitor: Real-time charts for CPU/memory/classes/threads
  • Threads: Thread state visualization, deadlock detection
  • Sampler: CPU/memory sampling analysis
  • Profiler: CPU/memory profiling (more accurate but higher overhead)
  • Heap Dump: Heap dump analysis, memory leak detection
# Launch VisualVM
jvisualvm

# Or download the standalone version
# https://visualvm.github.io/

Recommended plugins:

  • Visual GC: Visualize GC activity
  • BTrace Workbench: Dynamic tracing

JConsole

A lightweight monitoring tool bundled with the JDK, based on JMX:

jconsole <pid>

Features:

  • Memory usage trend charts (per memory pool)
  • Thread count and states
  • Class loading count
  • MBean operations
  • Deadlock detection

Java Flight Recorder (JFR)

JFR is a built-in low-overhead event collection framework in the JVM, freely available since JDK 11.

Core Concepts

  • Event: Records of actions occurring within the JVM, containing timestamps, threads, stack traces, etc.
  • Recording: An event collection session, configurable with duration and event types
  • Extremely low overhead: Typically < 2% performance impact, suitable for continuous production use

Usage

# Enable JFR at startup
java -XX:StartFlightRecording=duration=60s,filename=app.jfr ...

# Control via jcmd
jcmd <pid> JFR.start name=profiling duration=60s filename=app.jfr
jcmd <pid> JFR.dump name=profiling filename=dump.jfr
jcmd <pid> JFR.stop name=profiling

# Delayed start + continuous recording
jcmd <pid> JFR.start name=continuous settings=profile maxsize=100m maxage=1h

JFR Event Types

Category Event Examples
GC GC Pause, GC Phase, Heap Summary
Compilation JIT Compilation, Method Inline
Threads Thread Start/End, Thread Sleep, Thread Park
Locks Java Monitor Wait, Java Monitor Blocked
Memory Object Allocation in new TLAB, Object Allocation outside TLAB
IO File Read/Write, Socket Read/Write
Exceptions Exception Throw, Error Throw

Java Mission Control (JMC)

JMC is the analysis tool for JFR, providing a rich visual interface:

# Download
# https://www.oracle.com/java/technologies/jdk-mission-control.html

# Open a JFR recording file
jmc app.jfr

Core features:

  • GC analysis: Pause time distribution, per-generation usage curves
  • Memory analysis: Object allocation hotspots, TLAB allocation
  • Thread analysis: Blocking hotspots, lock contention
  • Method analysis: CPU hot methods, compilation events
  • IO analysis: File/network IO hotspots

Arthas

Arthas is an open-source Java diagnostic tool from Alibaba, designed for online troubleshooting without restarting the application.

# Install and launch
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

# Or attach directly to a process
java -jar arthas-boot.jar <pid>

Common Commands

# View dashboard (CPU/memory/threads/GC real-time data)
dashboard

# View thread information
thread                  # All threads
thread -n 3             # Top 3 threads by CPU usage
thread -b               # Find deadlocks

# Decompile a class
jad com.example.MyClass

# Monitor method invocations
monitor com.example.MyService process -c 10

# Trace method execution time
trace com.example.MyService process

# Observe method parameters and return values
watch com.example.MyService process "{params,returnObj}" -x 2

# View class information
sc -d com.example.MyClass

# View method call path
stack com.example.MyService process

# Hot-swap code
retransform /tmp/MyClass.java

# View current JVM information
jvm

# View GC information
memory

# Export heap dump
heapdump /tmp/heap.hprof

Prometheus + Grafana for JVM Monitoring

For production environments, Prometheus + Grafana is recommended for continuous monitoring.

Exposing JVM Metrics

# Option 1: JMX Exporter (recommended)
java -javaagent:jmx_prometheus_javaagent.jar=8080:config.jar -jar app.jar

# Option 2: Micrometer (Spring Boot applications)
# Add dependency + configuration
management.endpoints.web.exposure.include=prometheus
management.metrics.export.prometheus.enabled=true

Key Monitoring Metrics

Metric Description Alert Threshold
jvm_memory_used_bytes Memory usage > 85%
jvm_gc_pause_seconds GC pause time P99 > 500ms
jvm_gc_memory_promoted_bytes_total Objects promoted to old generation Steady growth
jvm_threads_current Current thread count > 500
jvm_classes_loaded Loaded class count Abnormal growth
process_cpu_usage Process CPU usage > 80%

Grafana Dashboard

Recommended pre-built dashboards to import:

  • JVM (Micrometer) - Dashboard ID: 4701
  • JMX Exporter - Dashboard ID: 11526

Tool Selection Guide

Scenario Recommended Tool Reason
Quick GC status check jstat Lightweight, no additional installation needed
View object distribution jmap -histo Quickly locate large objects
Memory leak investigation jmap -dump + MAT Complete heap analysis
Thread issue investigation jstack / Arthas thread View thread states and deadlocks
Online method tracing Arthas trace/watch No restart needed, real-time tracing
Deep performance analysis JFR + JMC Low overhead, rich events
Production continuous monitoring Prometheus + Grafana Real-time alerts, historical data

Summary

This chapter covered various JVM monitoring tools, from command-line to graphical interfaces. Command-line tools (jstat/jmap/jstack/jcmd) are suited for quick troubleshooting; JFR + JMC for deep performance analysis; Arthas for online diagnostics without restarting; and Prometheus + Grafana for continuous production monitoring. The next chapter will cover how to use these tools for diagnostics and troubleshooting.

Edit this page

Comments