Skip to content

Commit 0fddbea

Browse files
committed
docs: restore helper functions, runtime component docs, and troubleshooting
Rebalances the IMPLEMENTING_JRES.md rewrite — adds back lean sections for: - Helper function reference table (GetJREVersion, WriteJavaOpts, etc.) - profile.d script output example - Memory calculator: runtime output and user customization env vars - JVMKill: purpose, heap dump / volume service binding - Troubleshooting: JAVA_HOME, memory calculator, version resolution
1 parent f42c75e commit 0fddbea

1 file changed

Lines changed: 82 additions & 3 deletions

File tree

docs/IMPLEMENTING_JRES.md

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This guide explains how to implement new JRE providers for the Cloud Foundry Jav
1010
- [BaseJRE — Shared Implementation](#basejre--shared-implementation)
1111
- [Implementation Steps](#implementation-steps)
1212
- [Examples](#examples)
13+
- [Helper Functions](#helper-functions)
14+
- [Runtime Components](#runtime-components)
1315
- [Testing JREs](#testing-jres)
1416
- [Troubleshooting](#troubleshooting)
1517

@@ -235,16 +237,93 @@ Replace `<JREKEY>` with the uppercased `jreKey` value.
235237
bash scripts/unit.sh
236238
```
237239

240+
## Helper Functions
241+
242+
These are available in `src/java/jres/` and called by `BaseJRE` internally. You may need them if you implement a JRE that does not use `BaseJRE` (e.g. Zing).
243+
244+
| Function | Purpose |
245+
|----------|---------|
246+
| `GetJREVersion(ctx, jreKey)` | Resolves version from `BP_JAVA_VERSION`, `JBP_CONFIG_<KEY>_JRE`, then manifest default |
247+
| `DetectJREByEnv(jreKey)` | Returns `true` if `JBP_CONFIG_<KEY>_JRE` or `JBP_CONFIG_COMPONENTS` selects this JRE |
248+
| `WriteJavaHomeProfileD(ctx, jreDir, javaHome)` | Writes `profile.d/java.sh` exporting `JAVA_HOME`, `JRE_HOME`, and `PATH` |
249+
| `WriteJavaOpts(ctx, opts)` | Appends opts to the centralized `.opts` file consumed by `profile.d/00_java_opts.sh` |
250+
| `common.DetermineJavaVersion(javaHome)` | Reads `$JAVA_HOME/release` → returns Java major version as int |
251+
252+
### Version resolution priority
253+
254+
1. `BP_JAVA_VERSION` (e.g. `17`, `17.*`, `17.0.13`)
255+
2. `JBP_CONFIG_<JREKEY>_JRE` with `version:` field
256+
3. Manifest `default_versions` entry for this JRE key
257+
258+
### profile.d output
259+
260+
`WriteJavaHomeProfileD` produces `$DEPS_DIR/<idx>/.profile.d/java.sh`:
261+
262+
```bash
263+
export JAVA_HOME=$DEPS_DIR/0/jre/jdk-17.0.13
264+
export JRE_HOME=$DEPS_DIR/0/jre/jdk-17.0.13
265+
export PATH=$JAVA_HOME/bin:$PATH
266+
```
267+
268+
## Runtime Components
269+
270+
`BaseJRE` installs and finalizes these automatically. Documented here for operational reference.
271+
272+
### Memory Calculator
273+
274+
Downloads `java-buildpack-memory-calculator` binary. At application start it computes JVM heap/metaspace/stack settings from `$MEMORY_LIMIT`:
275+
276+
```
277+
-Xmx512M -Xms512M -XX:MaxMetaspaceSize=128M -Xss1M -XX:ReservedCodeCacheSize=32M
278+
```
279+
280+
User customization via env:
281+
282+
```bash
283+
cf set-env myapp MEMORY_CALCULATOR_STACK_THREADS 300
284+
cf set-env myapp MEMORY_CALCULATOR_HEADROOM 10 # % headroom to leave
285+
```
286+
287+
### JVMKill Agent
288+
289+
Native agent (`.so`) that kills the JVM on `OutOfMemoryError` or memory allocation failure, causing CF to restart the container cleanly instead of hanging.
290+
291+
Added to `JAVA_OPTS` as:
292+
```
293+
-agentpath:/home/vcap/deps/0/jre/bin/jvmkill-1.16.0.so=printHeapHistogram=1
294+
```
295+
296+
**Heap dump support:** if a volume service tagged `heap-dump` is bound, JVMKill writes heap dumps to the mounted volume:
297+
298+
```bash
299+
cf bind-service myapp my-nfs -c '{"mount":"/volumes/heap-dumps","tags":["heap-dump"]}'
300+
```
301+
238302
## Troubleshooting
239303

240-
**`findJavaHome` fails** — the tarball extracted to a directory that matches neither `dirPrefixes` nor `dirExacts`. Check the extraction layout:
304+
**`findJavaHome` fails** — tarball extracted to directory matching neither `dirPrefixes` nor `dirExacts`. Check layout:
241305

242306
```bash
243307
tar tf my-jre.tar.gz | head -5
244308
```
245309

246310
Add the top-level directory prefix/name to `dirPrefixes`/`dirExacts` accordingly.
247311

248-
**Install fails with "No matching dependency"** — check the `jreKey` in `newBaseJRE` matches the `name:` field in `manifest.yml` exactly.
312+
**Install fails with "No matching dependency"** — `jreKey` in `newBaseJRE` must match the `name:` field in `manifest.yml` exactly.
313+
314+
**`extraFinalizeOpts` not applied** — set the function on `b` (the `BaseJRE` value) before wrapping: `b.extraFinalizeOpts = func() string { ... }`. Setting it after `return &MyJRE{b}` has no effect.
315+
316+
**JAVA_HOME not set at runtime** — verify `profile.d/java.sh` exists:
317+
318+
```bash
319+
cf ssh myapp -- cat /home/vcap/deps/0/.profile.d/java.sh
320+
```
321+
322+
**Memory calculator not running** — verify binary exists and `MEMORY_LIMIT` is set:
323+
324+
```bash
325+
cf ssh myapp -- ls /home/vcap/deps/0/jre/bin/java-buildpack-memory-calculator-*
326+
cf ssh myapp -- echo $MEMORY_LIMIT
327+
```
249328

250-
**`extraFinalizeOpts` not applied** — ensure the function is set on `b` (the `BaseJRE` value) before wrapping it: `b.extraFinalizeOpts = func() string { ... }`. Setting it on the returned struct after `return &MyJRE{b}` has no effect.
329+
**Wrong Java version selected** — check resolution order: `BP_JAVA_VERSION` → `JBP_CONFIG_<KEY>_JRE` → manifest default. Enable debug: `cf set-env myapp BP_LOG_LEVEL DEBUG`.

0 commit comments

Comments
 (0)