JVM

On this page

JVM

The JVM page (Runtime, after System) shows what the Java virtual machine is doing, from the JDK management beans. No outside process is started. It is for admins; a viewer does not get it. Turn it off with collectors.jvm.enabled (or tabs.hide).

An old #threads link opens the Threads tab of this page.

Tabs

TabContent
OverviewThe JVM (name, vendor, version, PID, collector, JIT mode), heap used against the maximum, the Needs a look box and the history charts.
MemoryHeap and its generations, the heap after the latest collection, every memory pool (heap and non heap) with used, committed and maximum, direct and mapped buffers, open files. Run GC and heap dumps are here.
Garbage collectionTime in GC, bytes reclaimed, each collector (runs, total, average and longest pause), the last 100 collections with time, duration, cause and collector, and the causes with a short note.
ThreadsLive, daemon, peak and started threads, deadlocks, threads by state, and the thread list (BoxLang+).
Classes and JITClasses loaded and unloaded, the compiler, compile time and the code cache.
FlagsThe JVM arguments (secrets hidden), the effective values, and suggestions in plain words.

Everything may be missing on a JVM that does not report it. A value that cannot be read is shown as "not reported", never as zero.

Needs a look

The box lists a finding per check, each ok, warn or crit:

  • Heap steady or rising. Compares the lowest heap after a collection in the older half of the recorded collections with the lowest in the newer half. A rise of at least 5 percent of the maximum heap (never less than 32 MB) is a warning; it looks like a leak. The check waits for 8 collections over at least 5 minutes, so a young server says "not enough history yet" instead of guessing.
  • Heap nearly full after collection. Warn from 85 percent of the maximum, critical from 95 percent.
  • GC calm. Time in GC over the last 5 minutes: warn from 5 percent, critical from 15 percent.
  • Pauses over 100 ms in the recorded collections (critical from 1000 ms).
  • Humongous allocations (G1 collected because an object bigger than half a region was allocated).
  • Metaspace without a ceiling once it is 256 MB or more.
  • Deadlock (critical) and many blocked threads (10 or more and at least a tenth of all threads).

How the numbers are made

  • Collections come from a notification listener on every collector. It starts with BxLens, so collections before that are not in the ring. The totals per collector (runs, time) come from the JVM and are since it started.
  • Allocation rate is an approximation: the growth of the bytes allocated by all live threads (the last known value of a thread that ended is kept) between two samples 10 seconds apart. It misses what a thread allocated just before it ended. If the JVM does not support per thread counters, it falls back to heap growth plus the bytes the collections gave back.
  • History is a sample every 10 seconds, 90 samples, so the last 15 minutes. It lives in memory and is lost on restart.
  • Time in GC since start is the total collection time of the collectors over the uptime. Collectors that work while the application runs report their own time, so it can be more than the application feels as pauses.

Flags

Arguments that look sensitive are masked the same way as on the Environment page. The suggestions are rules, each true for the data: -Xms below -Xmx, no -Xmx, no metaspace ceiling, container support off, a 32-bit JVM or a tiny heap, humongous allocations seen, and code that calls System.gc(). When there is nothing to say, it says so.

Run GC and heap dumps

Run GC is free. Heap dumps need BoxLang+ or a trial. On Free the JVM page shows a BoxLang+ note instead of the heap dump controls and the server answers 403.

The Run GC and heap dump controls (the Memory tab) are for admins. A viewer does not see its buttons.

Run GC asks the JVM to run a garbage collection and shows the heap used before and after, the memory freed and the time it took. The JVM may pause briefly. The JVM can ignore the request if it runs with -XX:+DisableExplicitGC. Run GC is refused when console.readOnly is on.

A heap dump ready to download

Take a heap dump writes a .hprof file that you can open in a tool such as Eclipse MAT or VisualVM. It needs BoxLang+ or a trial, and it is off by default. Set console.allowHeapDump to true in boxlang.json to turn it on.

A heap dump holds everything in memory

The file contains passwords, session data, keys and personal data that were in memory. Lens cannot redact it. Turn the option on only when you need it, download the file over HTTPS, and handle it like a database backup. See Security.

How it works:

  • The page shows the estimated size and the free disk space, and asks for a confirmation. The JVM pauses while the file is written.
  • Lens needs free space in the temporary folder (java.io.tmpdir) of at least 1.2 times the heap in use. If there is less, it refuses to start.
  • It writes live objects only. A full garbage collection runs first, which also keeps the file smaller.
  • One dump at a time. While one is running or waiting for download, a new one is refused.
  • The file lives in a private temporary folder. Download it with Download .hprof, or press Discard.
  • Lens deletes the file 5 minutes after you download it, or 10 minutes after it was written if nobody downloads it. It also deletes it when the module stops.
  • console.readOnly does not block heap dumps. They have their own switch, console.allowHeapDump. A viewer cannot start or download one.
  • Every start, refusal, download and discard is written to the audit log.

Threads

The Threads tab lists every JVM thread with its state, CPU time and blocked time. It is a BoxLang+ page and for admins: on Free it shows a BoxLang+ note and the server answers 403, and a viewer does not get it. It refreshes every 5 seconds while open, not through the live stream, because taking a thread dump pauses the JVM briefly.

  • Filter by state (runnable, waiting, timed waiting, blocked), by pool, or by name or frame.

  • Threads running BoxLang templates or functions are marked BoxLang, and the thread that serves your own call is marked this request.

  • Pick a thread to see its stack. BoxLang frames are highlighted, and a waiting thread shows the lock and its owner. Copy the stack with one click.

  • Copy dump puts a jstack-style dump on the clipboard. Download dump saves it as lens-thread-dump-{timestamp}.txt. Download is for admins and is written to the audit log. A viewer cannot download it.

  • Badges on a row: holds N locks, blocked by (thread) and daemon. The row also shows the CPU use of the thread now, in percent of one core.

Threads: pools, badges, CPU now and the stack of a thread

Same stack: threads standing in the same place

Blocked chains: the thread that holds the lock and the threads waiting for it

Views

The Threads tab has four views.

ViewWhat it shows
ThreadsThe list above.
Same stackGroups of threads whose top 8 frames are identical: the count, the state, the top frame and up to five thread names. Many threads standing in one place is a queue at a lock, a slow call or a pool waiting for work, and the group says which.
Blocked chainsThreads grouped under the root holder: a thread that holds a lock others wait for and is not blocked itself. Each group shows the root, its top frame and how long it has been in that frame, then every thread that waits behind it (also through a middle thread) with the lock and how long. A deadlock has no such root, so one thread of the cycle stands as the root and the group is marked.
SnapshotsTake up to five snapshots (name, state, top 8 frames and CPU time per thread) and compare two. Threads with the same stack that are RUNNABLE or BLOCKED in both, and not parked or waiting, are listed as likely stuck.

A pool summary above the list groups threads by the pool name (the name without its trailing number): size, active (RUNNABLE), queued (the queue of the executor with the same name, shown only when there is one) and busy percent.

How the new numbers are made

  • CPU use comes from a small daemon sampler (bxlens-thread-sampler, every 5 seconds, at most 2000 threads, never inside a request). The percent is the thread CPU time between its last two samples over the wall time, so it is empty for the first seconds and for threads the sampler has not seen twice. It is empty (not zero) where the JVM has no thread CPU time.
  • How long a thread has been blocked or in the same top frame is how long the sampler has seen it so, so it can be shorter than the truth by up to one step, and it is empty for a thread the sampler has not seen in that state.
  • Locks held come from the dump that already includes monitors and synchronizers. The old keys of every thread stay unchanged.

Snapshots live in memory only (five at most, 1000 threads each, frames cut to 200 characters) and are dropped when the module stops. Taking one is admin only, BoxLang+ like the rest of the tab, and goes to the audit log as threads.snapshot.

Routes

RouteResult
GET threadsThe threads, with the old keys and, per thread, blockedBy ({ thread, lock } or null), waitingOn, heldLocks, daemon, cpuPct, stackKey, blockedForMs. At the top level blockedChains, sameStack, pools and snapshots next to threads, states, deadlocked and at.
POST threads/snapshotStores a snapshot and returns { id, at, threads, states }.
GET threads/snapshots{ snapshots: [...], max }, newest first.
GET threads/compare?a=<id>&b=<id>Per thread present in both sameStack, the states and the CPU spent between them, plus likelyStuck. 404 for an unknown id.

GET jvm has threads.pools (name, size, active, queued, busyPct) from the latest sample, and attention: the findings of the Needs a look box that are not ok, as { level: "crit" | "warn" | "info", id, title, text, link } with a link to the memory, gc or threads tab. findings stays as it was.

Deadlock

When the JVM reports a deadlock, the Threads tab shows a red banner with the number of threads involved. Under it, each deadlocked thread is listed with the lock it waits for and the thread that holds that lock, which shows the cycle. The banner has the same prompt buttons as an error, see Ask Lens and AI help. The Overview tab counts deadlocked threads too.

Edit this page Download Markdown Last updated Oct 26, 2026, 5:52:21 PM Report an issue