I'm using org.springframework.boot version 2.7.6 for project with spring_boot_starter org.springframework.boot:spring-boot-starter:2.7.6.

I'm building docker image with command:

./gradlew :osnap-applier:bootBuildImage --imageName="XXX"

With task configuration:

tasks.named("bootBuildImage") {
    environment = [
            "BPE_DELIM_JAVA_TOOL_OPTIONS" : " ",
            "BPE_APPEND_JAVA_TOOL_OPTIONS": " -XX:MaxDirectMemorySize=1G",
            "BPL_JVM_HEAD_ROOM"           : "5"
    ]
    imageName = "XXX"
}

In logs I can see correct head room settings:

[creator]     Paketo Buildpack for BellSoft Liberica 9.10.1
    [creator]       https://github.com/paketo-buildpacks/bellsoft-liberica
    [creator]       Build Configuration:
    [creator]         $BP_JVM_JLINK_ARGS           --no-man-pages --no-header-files --strip-debug --compress=1  configure custom link arguments (--output must be omitted)
    [creator]         $BP_JVM_JLINK_ENABLED        false                                                        enables running jlink tool to generate custom JRE
    [creator]         $BP_JVM_TYPE                 JRE                                                          the JVM type - JDK or JRE
    [creator]         $BP_JVM_VERSION              17.*                                                         the Java version
    [creator]       Launch Configuration:
    [creator]         $BPL_DEBUG_ENABLED           false                                                        enables Java remote debugging support
    [creator]         $BPL_DEBUG_PORT              8000                                                         configure the remote debugging port
    [creator]         $BPL_DEBUG_SUSPEND           false                                                        configure whether to suspend execution until a debugger has attached
    [creator]         $BPL_HEAP_DUMP_PATH                                                                       write heap dumps on error to this path
    [creator]         $BPL_JAVA_NMT_ENABLED        true                                                         enables Java Native Memory Tracking (NMT)
    [creator]         $BPL_JAVA_NMT_LEVEL          summary                                                      configure level of NMT, summary or detail
    [creator]         $BPL_JFR_ARGS                                                                             configure custom Java Flight Recording (JFR) arguments
    [creator]         $BPL_JFR_ENABLED             false                                                        enables Java Flight Recording (JFR)
    [creator]         $BPL_JMX_ENABLED             false                                                        enables Java Management Extensions (JMX)
    [creator]         $BPL_JMX_PORT                5000                                                         configure the JMX port
    **[creator]         $BPL_JVM_HEAD_ROOM           5                                                            the headroom in memory calculation**
    [creator]         $BPL_JVM_LOADED_CLASS_COUNT  35% of classes                                               the number of loaded classes in memory calculation
    [creator]         $BPL_JVM_THREAD_COUNT        250                                                          the number of threads in memory calculation
    [creator]         $JAVA_TOOL_OPTIONS                                                                        the JVM launch flags
    [creator]         Using Java version 17.* from BP_JVM_VERSION
    [creator]       BellSoft Liberica JRE 17.0.5: Reusing cached layer
    [creator]       Launch Helper: Reusing cached layer
    [creator]       Java Security Properties: Reusing cached layer

But when I run my container I have log which indicates that head room is not taken into account:

Setting Active Processor Count to 16
Calculating JVM memory based on 20082484K available memory
For more information on this calculation, see https://paketo.io/docs/reference/java-reference/#memory-calculator
Calculated JVM Memory Configuration: -Xmx18662370K -XX:MaxMetaspaceSize=74577K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 20082484K, Thread Count: 50, Loaded Class Count: 10753, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 124 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError  -XX:MaxDirectMemorySize=1G -XX:ActiveProcessorCount=16 -Xmx18662370K -XX:MaxMetaspaceSize=74577K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enable=true

As you can see head room is not set (Headroom: 0%) and if I increase/decrease head room setting, Xmx doesn't change.

I know that's probably a bug in BellSoft Liberica or libjvm, but I cannot understand how values are propagated through builtpacks. I tried to change the configuration in a way that violates https://github.com/paketo-buildpacks/libjvm/blob/main/helper/memory_calculator.go checks (e.g. set "BPL_JVM_LOADED_CLASS_COUNT": "abc", what should cause an error in line 88), but nothing happens and I cannot see any difference in my logs.

Comment From: scottfrederick

I know that's probably a bug in BellSoft Liberica or libjvm

Since we can see that the value set in the Gradle plugin environment is reflected in the output from the Bellsoft Liberica buidpack, anything that's not working as expected would have to be in buildpacks.

I would suggest building the same image using pack, to confirm that it is unrelated to Spring Boot. There is a java channel in the Paketo Slack org that is active, and that would be a good place to ask a question like this. Of course you could also open an issue in the Bellsoft Liberica buildpack repo.