I have a very weird issue with a project now. This...
# questions
u
I have a very weird issue with a project now. This project has 135 domain objects. Now if I add one more, making 136 domains(no matter how simple this object is). If I use JDK 24, then compileGroovy will fail with an heap overflow error. However, if I use jdk 17, the compile will pass. Did any of you see this before. Or if there are anything I can make the project working with JDK24? This happens with both Linux and Mac OS
u
* What went wrong: Execution failed for task ':compileGroovy'.
Java heap space
* Try:
Run with --debug option to get more log output.
Run with --scan to get full insights.
Get more help at https://help.gradle.org.
* Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':compileGroovy'. at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:130) at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:293) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:128) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:116) at org.gradle.api.internal.tasks.execution.ProblemsTaskPathTrackingTaskExecuter.execute(ProblemsTaskPathTrackingTaskExecuter.java:41) at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:210) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:205) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:54) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314) at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:85) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:459) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:376) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48) Caused by: java.lang.OutOfMemoryError: Java heap space at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:285) at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:67) at org.gradle.api.internal.tasks.compile.GroovyCompilerFactory$DaemonSideCompiler.execute(GroovyCompilerFactory.java:115) at org.gradle.api.internal.tasks.compile.GroovyCompilerFactory$DaemonSideCompiler.execute(GroovyCompilerFactory.java:99) at org.gradle.api.internal.tasks.compile.daemon.AbstractIsolatedCompilerWorkerExecutor$CompilerWorkAction.execute(AbstractIsolatedCompilerWorkerExecutor.java:78) at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63) at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:54)
u
Why Java 24/25 Causes Heap OOM During Compilation 1. Grails 7 Targets Java 17 Grails 7.0.2 is designed and tested against Java 17. Running it on Java 24/25 is unsupported territory — the Groovy AST transformation pipeline (which this project uses heavily: @Transactional, @CurrentTenant, etc.) wasn't built with Java 24/25 semantics in mind. 2. JPMS Module Restrictions (Main Culprit) Java 9+ introduced the module system. Each release tightens encapsulation of internal JDK APIs. By Java 24/25, many --add-opens that Groovy/Grails AST transformers rely on for reflection are blocked or removed. When reflection fails, the compiler falls back to: - More object allocations (wrappers, proxies) - Retrying via alternative paths - Keeping intermediate objects in memory longer (GC can't collect them) This creates memory pressure that doesn't exist on Java 17. 3. Groovy Metaclass Registry Groovy maintains a MetaClassRegistry for every class at compile time. On newer JVMs, due to module restrictions, Groovy creates additional wrapper metaclasses to work around inaccessible internals, multiplying heap usage. 4. Changed GC Ergonomics / Default Heap Java 24/25 changed default heap sizing heuristics. Counterintuitively, some configurations result in a smaller effective initial heap or different GC pressure timing — so OOM hits during the Groovy compile phase before GC can recover. --- Fixes (If You Must Use Java 21+) Option A — Increase Gradle JVM heap (in gradle.properties): org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m Option B — Add required --add-opens (also in gradle.properties): org.gradle.jvmargs=-Xmx4g \ --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.util=ALL-UNNAMED \ --add-opens java.base/java.io=ALL-UNNAMED Option C (Recommended) — Stay on Java 17 for this project. Grails 7 is certified on Java 17 and you'll avoid a class of subtle bugs beyond just the OOM. --------------- These are what Claude suggested.
u
I have no clue if these information is accurate anyway, so I will stay with Java 17
u
Please ignore this thread.
u
I eventually found out
Copy code
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx4g
in gradle.properties does not really increase the size of heap of compileGroovy. Somehow I have to do this in the build.gradle
Copy code
tasks.withType(GroovyCompile).configureEach {
    groovyOptions.fork = true
    groovyOptions.forkOptions.memoryMaximumSize = '4g'
}
Sorry for flooding the false information into the channel.
👍 2
👍🏼 1
👍🏻 1
s
@User your solution could prove valuable to others!
😂 1
🙏 1
1