Skip to content

Repository files navigation

JBM

JBM = Java Blocking Monitor

JBM is an agent that monitors JVM processes from the kernel using eBPF. It detects when an application thread is blocking for an extended period of time and generates a backtrace from the kernel to userspace. It then reports this information, providing valuable insights into blocking issues within your JVM applications.

Building

  1. Install rustup: https://rustup.rs/
  2. Install Rust and bpf-linker
rustup install stable
rustup toolchain install nightly --component rust-src
cargo install bpf-linker
  1. Build JBM
git clone https://github.com/kawamuray/jbm.git
cd jbm

# Build async-profiler
git submodule update --init
cd async-profiler
git submodule update --init
make -j8

cd ..

# Build JBM
cargo xtask build-ebpf --release
cargo build --release
# Now binrary is ready at:
./target/release/jbm

Usage

# Example usage for detecting "block" behavior defined as a thread stopped over a second but less than a minute
jbm -p TARGET_JVM_PID --min-block-time 1000000 --max-block-time 60000000

How it works

How it works

After startup JBM installs an eBPF program that adds kprobe for finish_task_switch function. By hooking finish_stask_switch function, we can detect when a task become off-cpu and on-cpu, hence by computing duration since last off, we can detect if a task has blocked for a long time. The target JVM gets the custom async-profiler attached. The eBPF program then sends an event when it detects long blocking, and user space control program zips the kernel space backtrace obtained by an event from eBPF with the event generated by the custom async-profiler running on the target JVM, which generates an event in response to receiving singnal from the eBPF program.

Derivative projects

  • jonoffcpu: Java Off CPU Profiler with async-profiler integration.

    jonoffcpu started as a fork of JBM and builds on the same idea: the kernel observes when a JVM thread leaves the CPU, and a signal to a patched async-profiler in the target JVM captures that thread's Java stack. It is actively maintained and extends the approach into a general off-CPU profiler:

    • Runs as a Java agent, with native libraries for both glibc and musl (for example Alpine) JVMs on x86-64 and arm64.
    • Keeps the observer effect small: the per-switch work stays in the kernel, and sampling modes (duration-proportional or uniform admission, with optional duration bounds) decide there which intervals are worth a signal and a stack walk, so the recording rate follows off-CPU time rather than the number of context switches.
    • Correlates offline: the capture writes compact records with each native stack stored once, and a separate correlator joins them with the async-profiler JFR recording afterwards, with memory that grows with the number of distinct stacks rather than the length of the capture.
    • Produces off-CPU flame graphs whose widths are measured durations, with alternative views of the same recording: intervals can be categorized as threads waiting for work or threads blocked while they had work to do, and stacks can be filtered and transformed (for example rooted at the application's first frame, with executor and lambda frames hidden) so that the application's boundaries become visible. Ranked reports list the application code that waited and what it waited on.
    • Uses an async-profiler fork that follows the master branch of async-profiler/async-profiler, with its patches rebased periodically.

    If you are looking for a maintained tool in the spirit of JBM, it may be a good fit.

License

JBM is licensed under the MIT License. You are free to use, modify, and distribute this software. See the LICENSE file for more information.

About

JVM Blocking Monitor

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages