Skip to content

Stop the resource guardrail from killing the JVM - #9

Merged
copyleftdev merged 1 commit into
mainfrom
fix/jvm-resource-budget
Aug 19, 2026
Merged

Stop the resource guardrail from killing the JVM#9
copyleftdev merged 1 commit into
mainfrom
fix/jvm-resource-budget

Conversation

@copyleftdev

Copy link
Copy Markdown
Owner

The first nightly run on main failed. Model checking died within a second and printed nothing; mutation testing and the simulation soak both passed.

Two bugs, and the second is why the first was invisible.

The guardrail killed the thing it was guarding

ulimit -v is the wrong instrument for a JVM. It reserves far more address space than it ever commits — compressed class space alone asks for a gigabyte before any heap — so a virtual ceiling sized to the intended heap stops it starting at all. It fails as Could not allocate compressed class space, which reads like a memory shortage and is actually the cap.

It never showed locally. This machine has enough RAM that a quarter share left plenty of headroom; the CI runner has 16GB, so the quarter share was 4GB and the JVM could not initialise.

The heap is capped with -Xmx now, which is the JVM's own instrument and precise about what it limits. ulimit -v still applies to native processes, where it does what it was meant to.

The failure explained nothing

The failure path filtered TLC's output through grep, and a grep that matches nothing exits non-zero — which under set -o pipefail aborted the script before printing. So the one run that failed was the one run with no diagnostic. It now prints the output unfiltered.

Verified

Reproduced the CI budget locally rather than guessing:

VERIFY_MEM_MB=3997 VERIFY_JOBS=2 TLC_HEAP=2g ./verify/tla.sh   -> both variants pass
TLC_HEAP=1m ...                                                -> "Too small maximum heap"

The second is the point: a starved run now says why instead of exiting mute.

The nightly run's model checking job failed within a second of starting, on
main, with no explanation printed. Two bugs, and the second is why the first
was invisible.

`ulimit -v` is the wrong instrument for a JVM. It reserves far more address
space than it ever commits — compressed class space alone asks for a
gigabyte before any heap — so a virtual ceiling sized to the intended heap
stops it starting at all. It fails as "Could not allocate compressed class
space", which reads like a memory shortage and is actually the guardrail.
This never showed locally because the machine it was written on has enough
RAM that a quarter of it left plenty of headroom; the CI runner has 16GB, so
the quarter share was 4GB and the JVM could not start.

The heap is capped with -Xmx instead, which is the JVM's own instrument and
is precise about what it limits. `ulimit -v` still applies to native
processes, where it does what it was meant to.

The silence was separate. The failure path filtered TLC's output through
grep, and a grep that matches nothing exits non-zero — which under
`set -o pipefail` aborted the script before it printed anything. The one run
that failed was the one run that explained nothing. It now prints the output
unfiltered.

Verified by reproducing the CI budget locally: passes at 3997MB, and a
deliberately starved heap now reports "Too small maximum heap" rather than
exiting mute.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@copyleftdev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6151c437-2518-4b06-96aa-2ca91b10c361

📥 Commits

Reviewing files that changed from the base of the PR and between 2294d0a and c65479e.

📒 Files selected for processing (2)
  • verify/budget.sh
  • verify/tla.sh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@copyleftdev
copyleftdev merged commit 10b2bba into main Aug 19, 2026
3 checks passed
@copyleftdev
copyleftdev deleted the fix/jvm-resource-budget branch August 19, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant