Backend Development 15 min read

Master JVM Performance: Essential Tools and Real-World Usage Guide

This article explains common JVM problems such as OutOfMemoryError, memory leaks, and thread deadlocks, then introduces core monitoring tools—jps, jstack, jmap/jhat, jstat, and hprof—detailing their syntax, options, and practical examples to help Java developers diagnose and tune production applications.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Master JVM Performance: Essential Tools and Real-World Usage Guide

In real‑world enterprise Java development you often encounter issues like OutOfMemoryError, memory leaks, thread deadlocks, lock contention, high CPU usage, and more. Understanding and solving these problems is essential for advancing as a Java programmer.

1. jps (Java Virtual Machine Process Status Tool) – Basic Tool

jps displays the JVM processes running on a host. Syntax:

jps [options] [hostid]

Common options:

-q   Do not output class name, JAR name, or main‑method arguments<br>-m   Output arguments passed to the main method<br>-l   Output the full package name of the main class or JAR<br>-v   Output the arguments passed to the JVM

Example:

# jps -m -l<br>2458 org.artifactory.standalone.main.Main /usr/local/artifactory-2.2.5/etc/jetty.xml<br>29920 com.sun.tools.hat.Main -port 9998 /tmp/dump.dat<br>3149 org.apache.catalina.startup.Bootstrap start<br>30972 sun.tools.jps.Jps -m -l<br>8247 org.apache.catalina.startup.Bootstrap start<br>25687 com.sun.tools.hat.Main -port 9999 dump.dat<br>21711 mrf-center.jar

2. jstack

jstack prints the thread stack traces of a Java process, which is invaluable for locating the code responsible for a problem.

jstack [option] pid<br>jstack [option] executable core<br>jstack [option] [server-id@]remote-hostname-or-ip

Key options:

-l   Long listings, prints additional lock information (useful for deadlock analysis)<br>-m   Mixed mode, includes native (C/C++) stack frames

Example workflow to find the most CPU‑intensive thread:

# ps -ef | grep mrf-center | grep -v grep<br>root 21711 1 1 14:47 pts/3 00:02:10 java -jar mrf-center.jar

Identify the hottest thread with

top -Hp 21711

, then convert its native thread ID to hexadecimal and grep it from jstack output:

# jstack 21711 | grep 54ee<br>"PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]

The stack trace shows the thread is waiting in

Object.wait()

, leading to the following idle‑wait code in the application:

// Idle wait<br>getLog().info("Thread [" + getName() + "] is idle waiting...");<br>schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;<br>long now = System.currentTimeMillis();<br>long waitTime = now + getIdleWaitTime();<br>long timeUntilContinue = waitTime - now;<br>synchronized(sigLock) {<br>    try {<br>        if (!halted.get()) {<br>            sigLock.wait(timeUntilContinue);<br>        }<br>    } catch (InterruptedException ignore) {}<br>}

3. jmap (Memory Map) and jhat (Java Heap Analysis Tool)

jmap exports heap memory; jhat analyzes the dump.

jmap [option] pid<br>jmap [option] executable core<br>jmap [option] [server-id@]remote-hostname-or-ip

Common usage:

# jmap -permstat 21711

To view heap configuration and usage:

# jmap -heap 21711

Sample output (truncated):

Heap Configuration:<br>MinHeapFreeRatio = 40<br>MaxHeapFreeRatio = 70<br>MaxHeapSize = 2067791872 (1972.0MB)<br>...<br>Heap Usage:<br>PS Young Generation<br>Eden Space: capacity = 6422528 (6.125MB), used = 5445552 (5.19MB)<br>...<br>PS Old Generation: capacity = 35258368 (33.63MB), used = 4119544 (3.93MB)

Histogram of object counts:

# jmap -histo:live 21711 | more<br>num   #instances   #bytes   class name<br>1:    38445        5597736  <constMethodKlass><br>2:    38445        5237288  <methodKlass><br>...<br>11:   14194        454208   java.lang.String<br>12:   3809         396136   java.lang.Class

Dump the heap to a file for analysis with jhat:

# jmap -dump:format=b,file=/tmp/dump.dat 21711

Analyze the dump:

# jhat -port 9998 /tmp/dump.dat

If the dump is large, increase the JVM heap for jhat:

# jhat -J-Xmx512m -port 9998 /tmp/dump.dat
jhat UI screenshot
jhat UI screenshot

4. jstat (JVM Statistics Monitoring Tool)

jstat reports memory and GC statistics.

jstat [generalOption | outputOptions vmid [interval[s|ms] [count]]]

Example showing GC info every 250 ms, four times:

# jstat -gc 21711 250 4<br>S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT<br>192.0 192.0 64.0 0.0 6144.0 1854.9 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649<br>...

Explanation of columns (Survivor, Eden, Old, Permanent generations, GC counts and times) follows the standard JVM heap layout diagram.

JVM heap layout
JVM heap layout

5. hprof (Heap/CPU Profiling Tool)

hprof can profile CPU usage and heap allocation.

java -agentlib:hprof[=options] ToBeProfiledClass<br>java -Xrunprof[:options] ToBeProfiledClass<br>javac -J-agentlib:hprof[=options] ToBeProfiledClass

Key options (excerpt):

heap=dump|sites|all   heap profiling (default: all)<br>cpu=samples|times|old CPU usage (default: off)<br>monitor=y|n          monitor contention (default: n)<br>format=a|b           text or binary output (default: a)<br>file=<file>          output file (default: java.hprof[.txt])<br>depth=<size>        stack trace depth (default: 4)<br>interval=<ms>       sampling interval (default: 10)

Example: CPU sampling profiling every 20 ms, depth 3:

java -agentlib:hprof=cpu=samples,interval=20,depth=3 Hello

Example: CPU times profiling (bytecode‑instrumented):

javac -J-agentlib:hprof=cpu=times Hello.java

Example: Heap allocation profiling (sites):

javac -J-agentlib:hprof=heap=sites Hello.java

Example: Full heap dump:

javac -J-agentlib:hprof=heap=dump Hello.java

Note: Using

-Xrunprof:heap=sites

on a production server can severely impact performance and is not recommended.

JVMmonitoringPerformancehprofjstackjmapjstat
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.