matrei commented on code in PR #16545:
URL: https://github.com/apache/grails-core/pull/16545#discussion_r4198528764


##########
grails-doc/src/en/guide/deployment/deploymentTasks.adoc:
##########
@@ -70,6 +70,58 @@ Heap is only part of total memory: allow space for 
metaspace, code cache, direct
 A container can be killed for exceeding its limit even if the Java heap has 
not run out of memory.
 Measure resident memory and GC behavior under load rather than copying a fixed 
heap percentage between applications.
 
+[[java25-memory]]
+=== Java 25 Memory Considerations

Review Comment:
   The new subsection is inserted in the middle of "Memory, storage, and 
logging". Everything after it in that section (`JAVA_TOOL_OPTIONS`/`JAVA_OPTS`, 
buildpacks, logging, storage, heap dumps, debug interfaces) now renders under 
the "Java 25 Memory Considerations" heading. Could you move it to the end of 
the section, just before `== Graceful shutdown and rolling updates`?



##########
grails-doc/src/en/guide/deployment/deploymentTasks.adoc:
##########
@@ -70,6 +70,58 @@ Heap is only part of total memory: allow space for 
metaspace, code cache, direct
 A container can be killed for exceeding its limit even if the Java heap has 
not run out of memory.
 Measure resident memory and GC behavior under load rather than copying a fixed 
heap percentage between applications.
 
+[[java25-memory]]
+=== Java 25 Memory Considerations
+
+Java 25 uses more off-heap memory than earlier LTS releases.
+The most significant change is that the metaspace — the native memory region 
that holds class metadata — is now **unbounded by default**.
+On earlier JDKs the initial metaspace high-water mark was approximately 12 MB; 
on Java 25 there is no upper limit unless you set one explicitly.
+A Grails application that loads many classes (plugins, Hibernate mappings, 
GSP-compiled views) can therefore consume substantially more native memory than 
the same application on Java 21.

Review Comment:
   > the metaspace … is now **unbounded by default**. On earlier JDKs the 
initial metaspace high-water mark was approximately 12 MB; on Java 25 there is 
no upper limit
   
   See the review summary: `MaxMetaspaceSize` is unlimited by default on 8+ 
([JDK 25 `java` 
reference](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html): 
"By default, the size isn't limited"), and `MetaspaceSize` (~21 MB on 17/21/25) 
is a GC trigger, not a limit. The same applies to "Java 25 uses more off-heap 
memory than earlier LTS releases": do we have a source or measurement for that?



##########
grails-doc/src/en/guide/deployment/deploymentTasks.adoc:
##########
@@ -70,6 +70,58 @@ Heap is only part of total memory: allow space for 
metaspace, code cache, direct
 A container can be killed for exceeding its limit even if the Java heap has 
not run out of memory.
 Measure resident memory and GC behavior under load rather than copying a fixed 
heap percentage between applications.
 
+[[java25-memory]]
+=== Java 25 Memory Considerations
+
+Java 25 uses more off-heap memory than earlier LTS releases.
+The most significant change is that the metaspace — the native memory region 
that holds class metadata — is now **unbounded by default**.
+On earlier JDKs the initial metaspace high-water mark was approximately 12 MB; 
on Java 25 there is no upper limit unless you set one explicitly.
+A Grails application that loads many classes (plugins, Hibernate mappings, 
GSP-compiled views) can therefore consume substantially more native memory than 
the same application on Java 21.
+
+In a container environment this matters most: the JVM heap limit (`-Xmx` or 
`-XX:MaxRAMPercentage`) does not cover metaspace, so a container sized only for 
the heap can be killed by the container runtime's OOM killer when metaspace 
grows beyond the remaining native memory budget.
+
+**Recommended settings for Java 25:**
+
+Set an explicit metaspace ceiling so the JVM raises `OutOfMemoryError: 
Metaspace` before the container runtime kills the process:
+
+[source,bash]
+----
+java -Xmx512m -XX:MaxMetaspaceSize=256m -Dgrails.env=prod -jar application.jar
+----
+
+Or, using percentage-based heap sizing in a container:
+
+[source,bash]
+----
+java -XX:MaxRAMPercentage=60.0 -XX:MaxMetaspaceSize=256m -Dgrails.env=prod 
-jar application.jar
+----
+
+Tune `-XX:MaxMetaspaceSize` from a measured baseline: run the application 
under representative load, observe the metaspace usage with `jcmd <pid> 
VM.metaspace` or a monitoring agent, and add a safety margin.
+A typical Grails application with Hibernate and a moderate number of plugins 
stabilizes between 128 MB and 256 MB of metaspace; a large application with 
many plugins may need more.
+
+If you also want to control how aggressively the JVM reclaims unused metaspace 
after a GC cycle, set the free-ratio bounds:
+
+[source,bash]
+----
+-XX:MinMetaspaceFreeRatio=20 -XX:MaxMetaspaceFreeRatio=80

Review Comment:
   > control how aggressively the JVM reclaims unused metaspace
   
   These flags set the headroom around the metaspace GC threshold after a 
collection. The example also doesn't match the description: the defaults are 
40/70, so `MaxMetaspaceFreeRatio=80` makes the JVM shrink *less* aggressively, 
and `MinMetaspaceFreeRatio=20` leaves less headroom, which means more frequent 
metaspace-triggered GCs. Without a concrete reason to tune them, I'd suggest 
removing this block.



##########
grails-doc/src/en/guide/deployment/deploymentStandalone.adoc:
##########
@@ -45,6 +45,7 @@ java -Xmx768m -Dgrails.env=prod -jar build/libs/myapp-0.1.jar 
\
 
 This example requires `/etc/myapp/` to exist. Place external `application.yml` 
or `application.properties` there.
 Size the heap for your workload and leave memory for metaspace, thread stacks, 
direct buffers, native libraries, and the operating system.
+On Java 25, metaspace is unbounded by default; see <<java25-memory,Java 25 
Memory Considerations>> for recommended settings.

Review Comment:
   > On Java 25, metaspace is unbounded by default
   
   Same issue: this is true on every JDK since 8 ([JDK 8 `java` 
reference](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html):
 "By default, the size is not limited"). Something like "Metaspace is unbounded 
by default; see <<…>> for recommended settings." would work.



##########
grails-doc/src/en/guide/upgrading/upgrading80x.adoc:
##########
@@ -4716,3 +4716,42 @@ for template renders:
 
 Objects passed with `bean` or `collection` are not part of `model`. See
 link:theWebLayer.html#definingInterceptors[Defining Interceptors].
+
+[[java25-memory-upgrade]]
+==== 85. Java 25 Memory Requirements

Review Comment:
   - This mostly repeats the deployment section, so the same factual issues 
apply here. The `UseCompressedClassPointers` bullets could also mention that 
the flag becomes obsolete (ignored) in JDK 27 
([JDK-8363996](https://github.com/openjdk/jdk/commit/da296cbea1)). I'd shorten 
the upgrade note to the actionable bits (consider setting `MaxMetaspaceSize`; 
remove `UseCompressedClassPointers`) and link to the deployment guide for the 
rest.
   - "Grails 8 supports Java 25 (the next LTS after Java 21)": this might fit 
better next to "1. Java 21 Minimum Requirement" than at the end as item 85.
   - Cross-chapter link: elsewhere this file links into other chapters with 
`link:<chapter>.html#<anchor>[...]` (e.g. 
`link:theWebLayer.html#definingInterceptors`). Could you confirm 
`<<java25-memory,...>>` resolves in the multi-page guide, or switch to 
`link:deployment.html#java25-memory[...]`?



##########
grails-doc/src/en/guide/deployment/deploymentTasks.adoc:
##########
@@ -70,6 +70,58 @@ Heap is only part of total memory: allow space for 
metaspace, code cache, direct
 A container can be killed for exceeding its limit even if the Java heap has 
not run out of memory.
 Measure resident memory and GC behavior under load rather than copying a fixed 
heap percentage between applications.
 
+[[java25-memory]]
+=== Java 25 Memory Considerations
+
+Java 25 uses more off-heap memory than earlier LTS releases.
+The most significant change is that the metaspace — the native memory region 
that holds class metadata — is now **unbounded by default**.
+On earlier JDKs the initial metaspace high-water mark was approximately 12 MB; 
on Java 25 there is no upper limit unless you set one explicitly.
+A Grails application that loads many classes (plugins, Hibernate mappings, 
GSP-compiled views) can therefore consume substantially more native memory than 
the same application on Java 21.
+
+In a container environment this matters most: the JVM heap limit (`-Xmx` or 
`-XX:MaxRAMPercentage`) does not cover metaspace, so a container sized only for 
the heap can be killed by the container runtime's OOM killer when metaspace 
grows beyond the remaining native memory budget.
+
+**Recommended settings for Java 25:**
+
+Set an explicit metaspace ceiling so the JVM raises `OutOfMemoryError: 
Metaspace` before the container runtime kills the process:
+
+[source,bash]
+----
+java -Xmx512m -XX:MaxMetaspaceSize=256m -Dgrails.env=prod -jar application.jar
+----
+
+Or, using percentage-based heap sizing in a container:
+
+[source,bash]
+----
+java -XX:MaxRAMPercentage=60.0 -XX:MaxMetaspaceSize=256m -Dgrails.env=prod 
-jar application.jar
+----
+
+Tune `-XX:MaxMetaspaceSize` from a measured baseline: run the application 
under representative load, observe the metaspace usage with `jcmd <pid> 
VM.metaspace` or a monitoring agent, and add a safety margin.
+A typical Grails application with Hibernate and a moderate number of plugins 
stabilizes between 128 MB and 256 MB of metaspace; a large application with 
many plugins may need more.

Review Comment:
   > A typical Grails application with Hibernate and a moderate number of 
plugins stabilizes between 128 MB and 256 MB of metaspace
   
   Where does this range come from? If it isn't measured, I'd drop the numbers 
and keep the "measure under load and add a margin" guidance. Readers will copy 
the `256m` cap, and an app that needs more will fail with `OutOfMemoryError: 
Metaspace` at runtime.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to