java_jfr_start
Start a Java Flight Recorder recording on a specified process to collect profiling data for memory leak analysis. Configure profile, duration, and output file.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pid | Yes | ||
| profile | No | profile | |
| duration_s | No | ||
| out_file | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/heap_seance_mcp/tools.py:157-202 (handler)The core implementation of java_jfr_start. It requires the 'jcmd' binary, builds a JFR.start command targeting the given PID with profile, duration, and output file, runs it, and returns an ok_result with the artifact path on success or a warn/error result on failure.
def java_jfr_start( pid: int, profile: str = "profile", duration_s: int = 30, out_file: str | None = None, ) -> dict[str, Any]: try: require_binary("jcmd", "Install OpenJDK 17+ so jcmd is available.") path = Path(out_file) if out_file else _artifact_dir() / f"jfr-{pid}-{_timestamp()}.jfr" path.parent.mkdir(parents=True, exist_ok=True) output = ensure_success( run_command( [ "jcmd", str(pid), "JFR.start", "name=HeapSeance", f"settings={profile}", f"duration={max(5, duration_s)}s", f"filename={str(path)}", ], timeout_s=max(60, duration_s + 15), ) ).stdout except Exception as exc: # noqa: BLE001 return _command_failed(exc) if not path.exists(): return warn_result( evidence=[ f"JFR command executed but expected output file was not found at {path}.", output.strip()[:800], ], metrics={"pid": pid, "requested_file": str(path)}, confidence="low", next_recommended_action="Check JFR permissions and rerun java_jfr_start with an explicit writable out_file.", ) return ok_result( evidence=[f"Recorded JFR capture for PID {pid} at {path}.", output.strip()[:800]], metrics={"pid": pid, "duration_s": duration_s, "profile": profile}, confidence="medium", next_recommended_action="Run java_jfr_summary on the generated recording.", raw_artifact_path=str(path), ) - src/heap_seance_mcp/server.py:39-51 (registration)MCP tool registration via @mcp.tool() decorator on a thin wrapper that delegates to tools.java_jfr_start.
@mcp.tool() def java_jfr_start( pid: int, profile: str = "profile", duration_s: int = 30, out_file: str | None = None, ) -> dict[str, Any]: return tools.java_jfr_start( pid=pid, profile=profile, duration_s=duration_s, out_file=out_file, ) - src/heap_seance_mcp/tools.py:157-162 (schema)Input schema: pid (int, required), profile (str, default 'profile'), duration_s (int, default 30), out_file (str | None, optional). Output is a dict with status, evidence, metrics, confidence, next_recommended_action, raw_artifact_path.
def java_jfr_start( pid: int, profile: str = "profile", duration_s: int = 30, out_file: str | None = None, ) -> dict[str, Any]: - src/heap_seance_mcp/workflow.py:24-28 (registration)Import of java_jfr_start in workflow.py for use in the deep analysis workflow.
java_jfr_start, java_jfr_summary, java_list_processes, java_mat_suspects, ) - Usage of java_jfr_start within the workflow's deep analysis mode with pid, profile='profile', duration_s=45.
jfr_result = java_jfr_start(pid=resolved_pid, profile="profile", duration_s=45) if jfr_result["status"] == "ok": report["artifacts"]["jfr"] = jfr_result["raw_artifact_path"] jfr_summary = java_jfr_summary(jfr_result["raw_artifact_path"]) if jfr_summary["status"] == "ok": jfr_signal = jfr_support_signal(jfr_summary["metrics"], monotonic) report["signals"]["jfr_support"] = jfr_signal else: report["evidence"].append( "JFR recording unreadable (possibly old JFR v0.9 format from Java 8). " "Continuing with histogram + GC + MAT evidence." ) else: report["evidence"].append(