From 17d9db0903ad421c9a8df43f6ef02d92f0771f0d Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Mon, 7 Sep 2026 13:32:27 +0200 Subject: [PATCH 1/3] chore: add .tool.yaml metadata --- .tool.yaml | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 .tool.yaml diff --git a/.tool.yaml b/.tool.yaml new file mode 100644 index 0000000..1e6f3d3 --- /dev/null +++ b/.tool.yaml @@ -0,0 +1,113 @@ +tag: ready +github_url: https://github.com/SAP/cf-cli-java-plugin +tagline: Cloud Foundry CLI plugin to troubleshoot Java apps running on CF without SSH. Trigger heap + dumps, thread dumps, and async-profiler or JFR recordings from the cf command line, with results + streamed back to your machine. Also embeds jstall for full JVM inspection via `cf java jstall`. +tagline_short: Trigger heap dumps, thread dumps, and profiles from the CF CLI — no SSH needed. +when_to_use: +- You run Java apps on Cloud Foundry and need heap dumps, thread dumps, or CPU profiles +- You want jstall-style JVM inspection without SSH access to the container +- You need to record JVM diagnostic data (status zip) for offline analysis +when_not_to_use: +- You are not using Cloud Foundry (use jstall directly for non-CF JVMs) +- You need real-time continuous profiling rather than one-shot diagnostics +related: +- label: jstall + url: https://github.com/parttimenerd/jstall +links: +- label: CF Plugin Registry ↗ + url: https://plugins.cloudfoundry.org/ +install: +- label: Latest (manual) + lang: bash + code: | + # Pick the binary for your platform: + cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/latest/download/cf-cli-java-plugin-macos-arm64 + # linux-amd64 / linux-arm64 / windows-amd64 also available +- label: CF Community + lang: bash + code: | + cf install-plugin -r CF-Community "java" + # Note: community repo lags behind GitHub releases +usage: +- label: Quick start + lang: bash + code: | + cf java heap-dump my-app + cf java thread-dump my-app + cf java jstall my-app +how_to: +- title: Take a heap dump from a running CF app + body: | + ```bash + cf java heap-dump $APP_NAME + ``` + Downloads `$APP_NAME-heapdump-.hprof` to your current directory. + Open it in VisualVM, Eclipse MAT, or IntelliJ's heap analyzer. + + **Note:** requires jmap, which is not bundled by default in the CF Java Buildpack. + Add a full JDK via `JBP_CONFIG_OPEN_JDK_JRE: '[jre: {version: 21.+}, jdk: {include: true}]'` + to your app's environment if you see a "jmap not found" error. + +- title: Get a thread dump and spot deadlocks + body: | + ```bash + cf java thread-dump $APP_NAME + ``` + Prints the full thread dump to stdout. To save it: + ```bash + cf java thread-dump $APP_NAME > thread-dump.txt + ``` + For a richer analysis including deadlock detection, hot threads, and lock graphs, use jstall: + ```bash + cf java jstall $APP_NAME --args 'deadlock all' + ``` + +- title: Profile CPU usage with async-profiler + body: | + ```bash + cf java asprof-start-cpu $APP_NAME + # reproduce the slow operation or wait 30–60 s + cf java asprof-stop $APP_NAME + # Downloads $APP_NAME-asprof-.jfr + ``` + Open the `.jfr` file in JDK Mission Control or IntelliJ to view the flame graph. + For a one-shot flame graph without manual start/stop, use jstall: + ```bash + cf java jstall $APP_NAME --args 'flame all' + ``` + +- title: Record a full diagnostic snapshot for offline analysis + body: | + ```bash + # Record everything (thread dump, heap histogram, jcmd output) into a zip: + cf java record-status $APP_NAME + + # Include JFR recording and flame graph (slower, larger): + cf java record-status $APP_NAME --full + + # Replay the zip locally with jstall: + jstall -f $APP_NAME-status.zip status all + jstall -f $APP_NAME-status.zip threads all + ``` + Useful for sharing diagnostics with teammates or filing bug reports without + giving them CF access. + +- title: Inspect a Cloud Foundry app with jstall + body: | + The plugin embeds jstall directly — no separate installation needed: + ```bash + # Full status report (deadlock detection, hot threads, etc.): + cf java jstall $APP_NAME + + # Run a specific jstall subcommand: + cf java jstall $APP_NAME --args 'most-work --dumps 3 all' + cf java jstall $APP_NAME --args 'flame all' + ``` + To use a newer jstall version than the one bundled in the plugin, + use jstall's own `--cf` option instead: + ```bash + jstall --cf $APP_NAME status all + ``` +note: Requires cf ssh to be enabled on the app (`cf enable-ssh my-app`, then restart). + The heap-dump command additionally needs jmap — see the How To entry above if it is missing. From d323b4d4d23e9759918845ac5ab62f8a42589175 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Mon, 7 Sep 2026 13:56:52 +0200 Subject: [PATCH 2/3] docs: add symptom-driven how-tos (unresponsive, high CPU, OOM) --- .tool.yaml | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/.tool.yaml b/.tool.yaml index 1e6f3d3..8aade3c 100644 --- a/.tool.yaml +++ b/.tool.yaml @@ -37,6 +37,60 @@ usage: cf java thread-dump my-app cf java jstall my-app how_to: +- title: My CF app is not responding — find what it is stuck on + body: | + Run `jstall` first — it detects deadlocks, identifies BLOCKED threads, and shows what + each thread is waiting for: + ```bash + cf java jstall $APP_NAME + ``` + If there is a deadlock, it will be listed at the top with the cycle of threads and monitors. + For a focused deadlock check only: + ```bash + cf java jstall $APP_NAME --args 'deadlock all' + ``` + If no deadlock, look for threads in `BLOCKED` state and the monitor they are waiting on. + The thread that *holds* that monitor is the bottleneck. For a plain thread dump: + ```bash + cf java thread-dump $APP_NAME + ``` + +- title: My CF app is using too much CPU + body: | + `most-work` takes repeated thread dumps and ranks threads by on-CPU frequency — + no async-profiler needed: + ```bash + cf java jstall $APP_NAME --args 'most-work --dumps 5 all' + ``` + For a proper CPU flame graph (slower, but much more detail): + ```bash + cf java jstall $APP_NAME --args 'flame all' + # Downloads an HTML flamegraph to your current directory + ``` + Or use the two-step async-profiler approach if you want to capture during a specific window: + ```bash + cf java asprof-start-cpu $APP_NAME + # reproduce the slow operation or wait 30–60 s + cf java asprof-stop $APP_NAME + # Downloads $APP_NAME-asprof-.jfr — open in JDK Mission Control + ``` + +- title: My CF app crashed with OutOfMemoryError — take a heap dump + body: | + Take a heap dump from the running (or restarted) instance and download it: + ```bash + cf java heap-dump $APP_NAME + # Downloads $APP_NAME-heapdump-.hprof to current directory + ``` + Analyse with hprof-analyzer for Leak Suspects and Top Consumers: + ```bash + hprof-analyzer $APP_NAME-heapdump-*.hprof report.html + # Open report.html → "Leak Suspects" and "Top Consumers" tabs + ``` + **Note:** requires jmap, which is not bundled by default in the CF Java Buildpack. + Add a full JDK via `JBP_CONFIG_OPEN_JDK_JRE: '[jre: {version: 21.+}, jdk: {include: true}]'` + to your app's environment if you see a "jmap not found" error. + - title: Take a heap dump from a running CF app body: | ```bash From e419c03dcf161168aaf25e584ecedb80861f2035 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Mon, 7 Sep 2026 14:01:15 +0200 Subject: [PATCH 3/3] docs: add Common Tasks section (unresponsive, high CPU, OOM) --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/README.md b/README.md index 3e9e15c..b114fb7 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,74 @@ cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/sn cf install-plugin https://github.com/SAP/cf-cli-java-plugin/releases/download/snapshot/cf-cli-java-plugin-linux-arm64 ``` +## Common Tasks + +### My CF app is not responding — find what it is stuck on + +Run `jstall` first — it detects deadlocks, identifies BLOCKED threads, and shows what +each thread is waiting for: + +```bash +cf java jstall $APP_NAME +``` + +If there is a deadlock, it will be listed at the top with the cycle of threads and monitors. +For a focused deadlock check only: + +```bash +cf java jstall $APP_NAME --args 'deadlock all' +``` + +If no deadlock, look for threads in `BLOCKED` state and the monitor they are waiting on. +The thread that *holds* that monitor is the bottleneck. For a plain thread dump: + +```bash +cf java thread-dump $APP_NAME +``` + +### My CF app is using too much CPU + +`most-work` takes repeated thread dumps and ranks threads by on-CPU frequency — +no async-profiler needed: + +```bash +cf java jstall $APP_NAME --args 'most-work --dumps 5 all' +``` + +For a proper CPU flame graph (slower, but much more detail): + +```bash +cf java jstall $APP_NAME --args 'flame all' +# Downloads an HTML flamegraph to your current directory +``` + +Or use the two-step async-profiler approach to capture a specific window: + +```bash +cf java asprof-start-cpu $APP_NAME +# reproduce the slow operation or wait 30–60 s +cf java asprof-stop $APP_NAME +# Downloads $APP_NAME-asprof-.jfr — open in JDK Mission Control +``` + +### My CF app crashed with OutOfMemoryError — take a heap dump + +Take a heap dump from the running (or restarted) instance and download it: + +```bash +cf java heap-dump $APP_NAME +# Downloads $APP_NAME-heapdump-.hprof to current directory +``` + +Analyse with [hprof-analyzer](https://github.com/parttimenerd/hprof-analyzer) for Leak Suspects and Top Consumers: + +```bash +hprof-analyzer $APP_NAME-heapdump-*.hprof report.html +# Open report.html → "Leak Suspects" and "Top Consumers" tabs +``` + +**Note:** requires jmap — see [Prerequisites](#prerequisites) if you see a "jmap not found" error. + ## Usage ### Prerequisites