skip to content

What is jstat, and how do you use it to monitor a running JVM's garbage collection?

level: juniorimportance: should knowfreq 35%

answer

  1. JDK tool, reads perfdata file = near-zero overhead
  2. Form: jstat -option pid interval count
  3. -gcutil = percentages; -gc = raw bytes
  4. Find PID with jps
  5. Counters (YGC/FGC/GCT) are cumulative — watch the rate

basics

~20 s

jstat is a command-line tool shipped with the JDK that prints live JVM statistics, mostly about memory and garbage collection. You point it at a running Java process by its PID and it can repeat at an interval, e.g. jstat -gcutil 12345 1000 prints GC stats every 1000 ms.

solid answer

~40 s

jstat (JVM Statistics Monitoring Tool) ships with the JDK and reports live runtime counters for a Java process without attaching a heavyweight profiler. You invoke it as `jstat -<option> <pid> [interval] [count]`; the PID comes from `jps` or the OS. Common options: `-gcutil` (percentage utilization of each memory region plus GC counts/times), `-gc` (raw capacities and used bytes), `-gccapacity` (min/max/current region sizes), `-class` (class loading), and `-compiler` (JIT). Adding an interval such as `1000` (milliseconds) makes it poll repeatedly, so you watch numbers change over time. It is low-overhead, read-only, works over the local file system (the perfdata file), and is ideal for a quick first look at whether an app is under memory pressure or churning through GC before reaching for a full profiler.

go deeper

for a junior

Knows jstat is a JDK command that prints live GC/memory stats for a Java PID, and that -gcutil with an interval polls repeatedly.

for a middle

Can name the common options (-gc, -gcutil, -gccapacity, -class, -compiler), explain that counters are cumulative, and find the PID with jps.

for a senior

Explains the perfdata/low-overhead mechanism, distinguishes percentage vs raw views, and uses jstat as the cheap first triage step before heap dumps/profilers.

for a principal

Positions jstat within an observability strategy (when JFR/GC logs/metrics pipelines are better), understands its limits for production fleets, and can script it for ad-hoc incident triage.

## What jstat is **jstat** stands for *JVM Statistics Monitoring Tool*. It is a small command-line program that comes bundled with the **JDK** (the Java Development Kit — the developer toolkit, as opposed to the JRE which only runs Java). Its job is to **print live numbers about a running Java process** — chiefly about memory and **garbage collection (GC)**, the JVM's automatic memory-reclamation system. ### Why it exists When a Java application seems slow or is running out of memory, you want to see *what the memory system is doing right now* without stopping the app or attaching a heavy tool. A full profiler can change the program's timing and adds overhead. jstat instead **reads counters the JVM already maintains** in a small shared file (the *perfdata* / `hsperfdata` file the JVM writes for each process), so it is extremely cheap and does not perturb the application. ### How you run it The general form is: ``` jstat -<option> <vmid> [<interval> [<count>]] ``` - **`<option>`** picks *which* statistics to show (see below). - **`<vmid>`** is the target JVM — usually just the OS **process id (PID)**. You find it with `jps` (another JDK tool that lists Java PIDs) or `ps`/Task Manager. - **`<interval>`** (optional) is how often to re-sample. By default it is in **milliseconds** (`1000` = once per second); you can suffix `s` or `ms`. - **`<count>`** (optional) is how many samples to print before exiting; omit it to run until you press Ctrl-C. Example: `jstat -gcutil 12345 1000` prints garbage-collection utilization for process 12345 once every second, forever. ### The main options - **`-gcutil`** — utilization of each memory region as a **percentage** (0–100), plus cumulative GC counts and times. The friendliest view for a quick health check. - **`-gc`** — the **raw numbers**: capacity and used bytes of each region (in kilobytes), plus GC counts/times. - **`-gccapacity`** — the **min/current/max sizes** each region is allowed to grow to. - **`-gcnew` / `-gcold`** — focus on just the young (new) generation or the old generation. - **`-class`** — class loading: how many classes loaded/unloaded and bytes. - **`-compiler` / `-printcompilation`** — the **JIT** (Just-In-Time) compiler activity. ### What the regions mean (you'll see these column names) The JVM heap is split for the generational garbage collector: - **Eden (E)** — where brand-new objects are allocated. - **Survivor spaces S0/S1 (S0, S1)** — where objects that survived a young-generation GC are copied. - **Old / tenured (O)** — long-lived objects promoted out of the young generation. - **Metaspace (M)** and **compressed class space (CCS)** — class metadata (this lives in native memory, not the heap, since Java 8). Counters you'll also see: **YGC/YGCT** = number of young (minor) collections and total time spent in them; **FGC/FGCT** = number of full (major) collections and their total time; **GCT** = total GC time. These are **cumulative since the JVM started**, so you watch how fast they *grow* between samples. ### Typical workflow 1. `jps` to find the PID. 2. `jstat -gcutil <pid> 1000` and watch for a few seconds. 3. If Old keeps climbing toward 100% and FGC keeps incrementing with growing FGCT, you have GC pressure (possibly a leak or undersized heap). Then escalate to a heap dump / profiler. In short: jstat is the **stethoscope** you reach for first — quick, read-only, low-overhead — before you bring out the MRI machine (a full profiler or heap-dump analyzer).

  • How do you find the PID to pass to jstat?
    Use `jps` (JVM Process Status tool, also in the JDK) to list running Java processes and their PIDs, or use the OS tools `ps`/Task Manager. jstat also accepts a full vmid that can target remote JVMs via a jstatd daemon, but locally the bare PID is enough.
  • Why prefer jstat over a full profiler for a first look?
    It is read-only and reads counters the JVM already maintains in a shared perfdata file, so overhead is negligible and it doesn't perturb timing. It's perfect for quickly confirming whether the symptom is GC/memory-related before investing in a heavier heap dump or profiling session.

saying these in an interview costs you the question

  • Thinking jstat is a profiler that shows method-level hotspots — it only shows aggregate JVM counters
  • Believing it adds significant overhead like instrumentation — it reads existing counters and is nearly free
  • Confusing jstat with jstack (thread dumps) or jmap (heap dumps)
  • Saying the interval is in seconds by default — it is milliseconds unless suffixed

context