Skip to content

Commit 9a533e6

Browse files
committed
Improve README
1 parent 619fd0d commit 9a533e6

1 file changed

Lines changed: 81 additions & 68 deletions

File tree

README.md

Lines changed: 81 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,10 @@ In case a proxy server is used, ensure that `cf ssh` is configured accordingly.
112112
[official documentation](https://docs.cloudfoundry.org/cf-cli/http-proxy.html#v3-ssh-socks5) of the Cloud Foundry
113113
Command Line for more information. If `cf java` is having issues connecting to your app, chances are the problem is in
114114
the networking issues encountered by `cf ssh`. To verify, run your `cf java` command in "dry-run" mode by adding the
115-
`-n` flag and try to execute the command line that `cf java` gives you back. If it fails, the issue is not in `cf java`,
116-
but in whatever makes `cf ssh` fail.
115+
`-n` flag and try to execute the command line that `cf java` gives you back. The plugin now wraps common SSH failures
116+
with user-facing guidance instead of printing the raw `ssh` error verbatim, so running the generated `cf ssh` command
117+
directly is the quickest way to inspect the underlying transport error. If that direct command fails, the issue is not
118+
in `cf java`, but in whatever makes `cf ssh` fail.
117119

118120
### Examples
119121

@@ -375,23 +377,84 @@ output the thread dump to file before streaming it out.)
375377

376378
## Limitations
377379

378-
The capability of creating heap dumps and profiles is also limited by the filesystem available to the container. The
379-
`cf java heap-dump`, `cf java asprof-stop` and `cf java jfr-stop` commands trigger a write to the file system, read the
380-
content of the file over the SSH connection, and then remove the file from the container's file system (unless you have
381-
the `-k` flag set). The amount of filesystem space available to a container is set for the entire Cloud Foundry
382-
landscape with a global configuration. The size of a heap dump is roughly linear with the allocated memory of the heap
383-
and the size of the profile is related to the length of the recording. So, it could be that, in case of large heaps,
384-
long profiling durations or the filesystem having too much stuff in it, there is not enough space on the filesystem for
385-
creating the file. In that case, the creation of the heap dump or profile recording and thus the command will fail.
380+
Some commands depend on writable filesystem space inside the application container. In particular,
381+
`cf java heap-dump`, `cf java asprof-stop`, and `cf java jfr-stop` first create a file in the container, then stream
382+
that file back over SSH, and finally remove it again unless the `-k` flag is set.
386383

387-
From the perspective of integration in workflows and overall shell-friendliness, the `cf java` plugin suffers from some
388-
shortcomings in the current `cf-cli` plugin framework:
384+
The available container filesystem space is controlled by the Cloud Foundry landscape configuration and may be limited.
385+
Heap dumps can be large, roughly scaling with heap usage, and profile files can also grow substantially depending on
386+
recording duration and settings. If the container does not have enough free space, the dump or recording cannot be
387+
created and the command will fail.
388+
389+
The plugin is also constrained by limitations in the current `cf-cli` plugin framework:
389390

390391
- There is no distinction between `stdout` and `stderr` output from the underlying `cf ssh` command (see
391392
[this issue on the `cf-cli` project](https://github.com/cloudfoundry/cli/issues/1074))
392-
- The `cf java` will however (mostly) exit with status code `1` when the underpinning `cf ssh` command fails
393-
- If split between `stdout` and `stderr` is needed, you can run the `cf java` plugin in dry-run mode (`--dry-run`
394-
flag) and execute its output instead
393+
- `cf java` will still usually exit with status code `1` when the underlying `cf ssh` command fails
394+
- If you need separate `stdout` and `stderr`, run the plugin in dry-run mode (`--dry-run`) and execute the generated
395+
command directly
396+
397+
### Known Command Limitations
398+
399+
#### jstall Flame Graph May Fail in Containerized Environments
400+
401+
The `jstall flame` command may fail with an error like:
402+
```
403+
Error: profiling was skipped: profiling-failed
404+
jstall execution failed: exit status 1
405+
```
406+
407+
**Reason:** Flame graph generation depends on low-level profiling capabilities such as `perf` events. These are often
408+
restricted in containerized environments for security reasons.
409+
410+
**Workarounds:**
411+
412+
1. Use async-profiler directly for CPU profiling:
413+
```bash
414+
cf java asprof-start-cpu $APP_NAME
415+
# ... wait for profiling ...
416+
cf java asprof-stop $APP_NAME
417+
```
418+
419+
2. Use other jstall commands that don't require perf:
420+
```bash
421+
cf java jstall $APP_NAME --args 'status all' # JVM status & diagnostics
422+
cf java jstall $APP_NAME --args 'deadlock all' # Deadlock detection
423+
cf java jstall $APP_NAME --args 'threads all' # Thread information
424+
```
425+
426+
3. Record diagnostic data for later analysis:
427+
```bash
428+
cf java record-status $APP_NAME diagnostics.zip
429+
# Then replay locally
430+
jstall -f diagnostics.zip status all
431+
```
432+
433+
#### SSH Connection Failures
434+
435+
When the plugin cannot establish SSH connectivity, it reports a categorized error message with likely causes and
436+
suggested next steps instead of only printing the raw `cf ssh` transport error. A typical message looks like:
437+
```
438+
Cannot connect to app 'APP_NAME' via SSH.
439+
Possible causes and solutions:
440+
1. SSH may not be enabled on the application. Try:
441+
cf enable-ssh APP_NAME
442+
cf restart APP_NAME
443+
2. Check your network connection and firewall settings.
444+
3. Verify the application is running: cf app APP_NAME
445+
```
446+
447+
**Common causes and fixes:**
448+
449+
| Error | Likely Cause | Solution |
450+
|-------|------|----------|
451+
| `connection refused` or `not enabled` | SSH not enabled on application | `cf enable-ssh APP_NAME && cf restart APP_NAME` |
452+
| `connection reset` | Network interruption | Retry the command; check internet connection |
453+
| `timeout` | Network unreachable | Check firewall/proxy settings; verify platform connectivity |
454+
| `Permission denied` | Authentication failed | `cf logout && cf login` with correct credentials |
455+
456+
**Debugging:** If you need the original SSH transport error from Cloud Foundry, run `cf ssh APP_NAME -c 'echo ok'`
457+
directly.
395458

396459
## Side-effects on the running instance
397460

@@ -441,60 +504,10 @@ make build
441504
development build from GitHub Actions instead, use:
442505

443506
```bash
507+
JSTALL_DEV=1 make build
444508
445-
### Known Command Limitations
446-
447-
#### jstall Flame Graph May Fail in Containerized Environments
448-
449-
The `jstall flame` command may fail with error:
450-
```
451-
Error: profiling was skipped: profiling-failed
452-
jstall execution failed: exit status 1
453-
```
454-
455-
**Reason:** Flame graph generation requires system-level profiling capabilities (perf events) that may be restricted
456-
in containerized environments for security reasons.
457-
458-
**Workarounds:**
459-
460-
1. Use async-profiler directly for CPU profiling:
461-
```bash
462-
cf java asprof-start-cpu $APP_NAME
463-
# ... wait for profiling ...
464-
cf java asprof-stop $APP_NAME
465-
```
466-
467-
2. Use other jstall commands that don't require perf:
468-
```bash
469-
cf java jstall $APP_NAME --args 'status all' # JVM status & diagnostics
470-
cf java jstall $APP_NAME --args 'deadlock all' # Deadlock detection
471-
cf java jstall $APP_NAME --args 'threads all' # Thread information
472-
```
473-
474-
3. Record diagnostic data for later analysis:
475-
```bash
476-
cf java record-status $APP_NAME diagnostics.zip
477-
# Then replay locally
478-
jstall -f diagnostics.zip status all
479-
```
480-
481-
#### SSH Connection Failures
482-
483-
Commands may fail with SSH connection errors like:
484-
```
485-
ssh: handshake failed: read tcp X.X.X.X:XXXXX->X.X.X.X:2222: read: connection reset by peer
486-
```
487-
488-
**Common causes and fixes:**
489-
490-
| Error | Likely Cause | Solution |
491-
|-------|------|----------|
492-
| `connection refused` or `not enabled` | SSH not enabled on application | `cf enable-ssh APP_NAME && cf restart APP_NAME` |
493-
| `connection reset` | Network interruption | Retry the command; check internet connection |
494-
| `timeout` | Network unreachable | Check firewall/proxy settings; verify platform connectivity |
495-
| `Permission denied` | Authentication failed | `cf logout && cf login` with correct credentials |
496-
497-
**Debugging:** Use `cf ssh APP_NAME -c 'echo ok'` to test SSH connectivity directly.
509+
# Or download a specific GitHub Actions run by ID
510+
JSTALL_DEV=<run-id> make build
498511
```
499512

500513
This pulls the latest JStall build directly from the GitHub Actions artifacts instead of the released version.

0 commit comments

Comments
 (0)