What happens
We reuse a Spring Boot fat jar as a one-off task (a DB migration) via cf run-task:
JBP_CONFIG_JAVA_MAIN: '{ java_main_class: "org.springframework.boot.loader.launch.PropertiesLauncher" }'
JAVA_OPTS: "-Dloader.main=com.example.task.DbMigrationRunner"
The app manifest says memory: 2048M, but the task OOMs immediately. The memory calculator sizes the heap to -Xmx5877K.
Why (short version)
cf run-task does not use the app's memory:. The task uses a platform default, e.g. 768M.
- The buildpack's auto class count is 45000 (it counts the whole fat jar), which makes metaspace huge. At 768M there's nothing left for the heap.
Both the memory calc invocation and the class count are decided at staging and baked into the droplet — identical for the web and task process types.
(Full analysis, verified against memory-calculator 4.2.0 — the exact numbers, the -Xmx behaviour, and the workarounds we tried — is in this gist)
Note — immediate mitigation
You can give the task more memory so the heap doesn't collapse, either ad-hoc:
or by pointing it at a manifest process sized for the task (see multiple-processes):
cf run-task APP --process worker
This works around it today, but doesn't address the default behaviour below.
Up for discussion
- Should a
task process get leaner memory defaults than web (fewer threads / lower assumed class count)? The buildpack already emits a separate task command, it's just identical to web today.
- Should the buildpack warn (instead of silently producing a ~5MB heap) when the computed heap collapses?
- What's the intended way to tune memory for a one-off task, given
class_count / stack_threads are staging-time only and cf run-task has no per-task env?
Looking for maintainer guidance on the right direction before proposing a change.
We can at least update the docs on how run-task behaves.
What happens
We reuse a Spring Boot fat jar as a one-off task (a DB migration) via
cf run-task:The app manifest says
memory: 2048M, but the task OOMs immediately. The memory calculator sizes the heap to-Xmx5877K.Why (short version)
cf run-taskdoes not use the app'smemory:. The task uses a platform default, e.g. 768M.Both the memory calc invocation and the class count are decided at staging and baked into the droplet — identical for the
webandtaskprocess types.(Full analysis, verified against memory-calculator 4.2.0 — the exact numbers, the
-Xmxbehaviour, and the workarounds we tried — is in this gist)Note — immediate mitigation
You can give the task more memory so the heap doesn't collapse, either ad-hoc:
or by pointing it at a manifest process sized for the task (see multiple-processes):
This works around it today, but doesn't address the default behaviour below.
Up for discussion
taskprocess get leaner memory defaults thanweb(fewer threads / lower assumed class count)? The buildpack already emits a separatetaskcommand, it's just identical towebtoday.class_count/stack_threadsare staging-time only andcf run-taskhas no per-task env?Looking for maintainer guidance on the right direction before proposing a change.
We can at least update the docs on how run-task behaves.