Control Java Flight Recorder (JFR) from Neovim.
This plugin was generated using AI.
- Start / stop / dump recordings via
jcmd - Monitor active recordings in-editor
- Save recordings under your project (
<root>/.jfr/recordings) - Open
.jfrin JDK Mission Control (JMC)
nvim-jfr brings the common “profile a JVM” loop into your editor:
- Start a recording
- Monitor while it runs
- Stop (or dump) to a
.jfrfile - Open the result in JMC
- Browse/manage recordings
It is designed around a project-local layout:
- Recordings:
<root>/.jfr/recordings/ - Templates:
<root>/.jfr/templates/
For the shortest guide, see: docs/recording-workflow.md
- Neovim 0.8.0+
- JDK 8+ with
jcmdavailable onPATH
Optional:
jmc(or a configuredjmc_command) to open recordings in Mission Controljfrto enable:JFRRecordingspreview (jfr summary) when enabled
Using lazy.nvim:
{
"CrystalMethod/nvim-jfr",
cmd = { "JFRStart", "JFRStatus", "JFRStop", "JFRDump", "JFRRecordings" },
opts = {},
}If you want all commands available for lazy-loading:
{
"CrystalMethod/nvim-jfr",
cmd = {
"JFRStart",
"JFRStop",
"JFRDump",
"JFRStatus",
"JFRRecordings",
"JFRCapabilities",
"JFCNew",
},
opts = {},
}" 1) Start a recording
:JFRStart --settings=profile --duration=60s
" Skip named run configuration selection (if you use run configs)
:JFRStart --run=none
" 2) Monitor while it runs
:JFRStatus
" 3) Stop + save (or dump without stopping)
:JFRStop
" or:
:JFRDump
" 4) Browse/manage saved recordings
:JFRRecordings| Command | Purpose | Typical usage |
|---|---|---|
:JFRStart |
Start a recording | :JFRStart --settings=profile --duration=60s |
:JFRStatus |
Monitor active recordings | :JFRStatus |
:JFRStop |
Stop + save recording(s) | :JFRStop |
:JFRDump |
Dump without stopping | :JFRDump |
:JFRRecordings |
Browse/manage saved .jfr files |
:JFRRecordings |
| Command | When to use |
|---|---|
:JFRCapabilities |
Inspect what the target JVM supports (option gating, JFR.start help, etc.) |
:JFCNew |
Copy a .jfc template into <root>/.jfr/templates/ |
Stop all recordings for a JVM:
:JFRStop --all=true " confirm
:JFRStop! " no confirmationDump selection behavior:
:JFRDump " dumps the latest/only recording (no-args is useful)
:JFRDump! " always pick recording(s)
:JFRDump --pick=true " always pick recording(s)When output_dir = "project" (default), recordings are saved under:
<root>/.jfr/recordings/
Create a project-local .jfc from a template:
:JFCNewThen start a recording using it:
:JFRStart --settings=<root>/.jfr/templates/your.jfc --duration=60sFor editing .jfc (XML), use an XML LSP (e.g. LemMinX) for validation/formatting.
See also: docs/jfc-authoring.md.
For the complete configuration reference, see CONFIG.md.
Optional: named run configurations: docs/run-configs.md.
Note: if you have many JVMs running, keep pickers snappy by leaving
show_java_version_in_picker = false (default) and by excluding tooling JVMs
(jdtls, mvnw, etc.) via project_jvm_probe.exclude_raw_patterns (see CONFIG).
require("nvim-jfr").setup({
-- Output directory for recordings
-- "project" = <project-root>/.jfr/recordings when a project root is detected
-- nil = platform default (~/jfr-recordings on Unix, %USERPROFILE%\jfr-recordings on Windows)
output_dir = "project",
-- Default `settings=` value passed to `jcmd <pid> JFR.start`.
-- Supported values:
-- - "default" | "profile" (built-in templates)
-- - "/path/to/custom.jfc" (custom settings file)
settings = "profile",
-- Picker: "snacks", "telescope", "fzf", "vim", "auto"
picker = "auto",
-- Command to open JFR files (JDK Mission Control)
jmc_command = "jmc",
}):JFRStart --settings=profile --duration=60s
:JFRStatus
:JFRStop
:JFRRecordings:JFRDumpSet output_dir = "project" (this is the default).
Run:
:checkhealth nvim-jfrThis checks:
- Neovim version and required APIs (
vim.fs.find,vim.uv/vim.loop) - Your
nvim-jfrconfiguration (common type/value mistakes) - Picker backend availability (Snacks/Telescope/fzf-lua/vim.ui.select)
- Output directory resolution + basic writability checks
- External tools on
PATH(or via config):jcmd/java(required),jfr/jmc(optional)
- Ensure your Java application is running
- Verify
jcmd -lworks from a terminal
- For JDK 8, start the JVM with:
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder(or vendor equivalent) - Check:
jcmd <pid> help JFR.start
- Run Neovim as the same OS user that owns the JVM process
- On Linux, check ptrace restrictions (e.g.
/proc/sys/kernel/yama/ptrace_scope)
:checkhealth nvim-jfr- Open an issue with:
- your OS + Neovim version
- your JDK version
- the output of
:checkhealth nvim-jfr
nvim-jfr/
├── plugin/
│ └── nvim-jfr.lua # User command registration
├── lua/nvim-jfr/
│ ├── commands.lua # :JFR* command implementations
│ ├── jfr.lua # jcmd wrapper + JFR.* operations
│ ├── jvm.lua # JVM discovery (jcmd -l)
│ ├── status.lua # Status UI
│ ├── recordings.lua # Output dir + file helpers
│ ├── picker.lua # Picker abstraction
│ └── ...
└── docs/ # Additional markdown docs
└── recording-workflow.md
This repo uses small headless specs that can be executed with Neovim:
nvim --headless -u NONE -c "set rtp+=." -c "lua assert(require('nvim-jfr.commands_spec').run())" -c "qa"