jamesfredley commented on code in PR #16545:
URL: https://github.com/apache/grails-core/pull/16545#discussion_r4340490158
##########
grails-doc/src/en/guide/upgrading/upgrading80x.adoc:
##########
@@ -4837,3 +4837,40 @@ With `DISCRIMINATOR` multi-tenancy, GORM for MongoDB,
GORM for Neo4j and GORM's
* Without a current tenant, these methods throw `TenantNotFoundException`, as
a query does. `getAll` without ids still returns an empty list.
* Inside `Tenants.withoutId { }` a lookup by id is still not restricted to a
tenant, and neither is a proxy returned by `load` or `proxy` that is
initialized there. As the previous note says, only `withoutId` lifts the
restriction: a tenant id of `default` restricts a lookup by id to that tenant
as it restricts a query.
* A lookup by id still finds an instance that the session holds for the
current tenant, including one that has been saved but not flushed, and it does
not flush the session.
+
+
+[[java25-memory-upgrade]]
+==== 88. Java 25 Memory Requirements
+
+Grails 8 supports Java 25 (the next LTS after Java 21).
+Java 25 uses more off-heap memory than Java 21, and the most significant
change is that the **metaspace is now unbounded by default**.
+On Java 21 and earlier, the JVM imposed an initial high-water mark of
approximately 12 MB on metaspace growth; on Java 25 there is no upper limit
unless you set one explicitly.
+
+A Grails application loads a large number of classes — plugins, Hibernate
entity mappings, GSP-compiled views, Spring beans — so metaspace can grow well
beyond what earlier JDKs allowed without intervention.
+In a container environment this is especially important: the 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.
+
+**What to do when running on Java 25:**
+
+Set an explicit metaspace ceiling with `-XX:MaxMetaspaceSize` 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 metaspace usage with `jcmd <pid>
VM.metaspace`, and add a safety margin.
+
+The `-XX:+/-UseCompressedClassPointers` flag is deprecated in Java 25 and will
be removed in a future release.
+
+* If your startup scripts pass `-XX:+UseCompressedClassPointers` (the
default), remove it — it is superfluous.
+* If they pass `-XX:-UseCompressedClassPointers` to disable compressed class
pointers, remove it.
+If you encounter class-space exhaustion after removing it, increase the class
space with `-XX:CompressedClassSpaceSize=4g` instead.
Review Comment:
This is the same combination that does not work. The examples above set
`-XX:MaxMetaspaceSize=256m`. On Java 25, HotSpot then reduces
`-XX:CompressedClassSpaceSize=4g` to the same class-space reservation it would
have used without the flag (about 208 MiB under a 256m metaspace ceiling).
Raising class-space size alone does not relieve exhaustion while that ceiling
stays.
Remove this residual recommendation, or say that the metaspace ceiling, the
class-space reservation, and the container budget have to be raised together.
Do not present `CompressedClassSpaceSize=4g` as the remedy next to the 256m
examples.
##########
grails-doc/src/en/guide/upgrading/upgrading80x.adoc:
##########
@@ -4837,3 +4837,40 @@ With `DISCRIMINATOR` multi-tenancy, GORM for MongoDB,
GORM for Neo4j and GORM's
* Without a current tenant, these methods throw `TenantNotFoundException`, as
a query does. `getAll` without ids still returns an empty list.
* Inside `Tenants.withoutId { }` a lookup by id is still not restricted to a
tenant, and neither is a proxy returned by `load` or `proxy` that is
initialized there. As the previous note says, only `withoutId` lifts the
restriction: a tenant id of `default` restricts a lookup by id to that tenant
as it restricts a query.
* A lookup by id still finds an instance that the session holds for the
current tenant, including one that has been saved but not flushed, and it does
not flush the session.
+
+
+[[java25-memory-upgrade]]
+==== 88. Java 25 Memory Requirements
+
+Grails 8 supports Java 25 (the next LTS after Java 21).
+Java 25 uses more off-heap memory than Java 21, and the most significant
change is that the **metaspace is now unbounded by default**.
Review Comment:
Metaspace is not newly unbounded in Java 25. It has been unlimited by
default since JDK 8, including Java 21. `MetaspaceSize` is the initial GC
high-water mark, not a growth ceiling, and it still exists on Java 25. The
deployment page in this same pull request says that correctly.
Say that both Java 21 and Java 25 leave metaspace unlimited unless
`MaxMetaspaceSize` is set. Do not tell someone upgrading from Java 21 that
earlier JDKs required intervention before metaspace could grow past about 12 MB.
--
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]