projectlombok / lombok

Very spicy additions to the Java programming language.
https://projectlombok.org/
Other
12.9k stars 2.39k forks source link

[BUG] GC overhead limit exceeded while compiling #2240

Open dmuatdbh opened 5 years ago

dmuatdbh commented 5 years ago

When compiling one of out product java-source, we get an OutOfMemoryError after a while. We compile with up to 4GB of RAM.

We can simply reproduce the OOME when compiling the sources. We tried lombok 1.18.4 and upgraded to 1.18.9, but the result remains. The heapDump (up to 3 GB) shows, that lombok addresses 1.5 GB of memory.

Here is the stackTrace:

[ant:javac] javac 1.8.0_151
[ant:javac] java.lang.OutOfMemoryError: GC overhead limit exceeded
[ant:javac] Dumping heap to ./myDump.hprof ...
[ant:javac] Heap dump file created [2849283070 bytes in 12.903 secs]
[ant:javac]
[ant:javac]
[ant:javac] An annotation processor threw an uncaught exception.
[ant:javac] Consult the following stack trace for details.
[ant:javac] java.lang.OutOfMemoryError: RegularFileObject[C:\oo\dev\ac\source\de\logas\statistik\StatistikPackageFacade.java]@pos5802: RegularFileObject[C:\oo\dev\ac\source\de\logas\statistik\StatistikPackageFacade.java]@pos5873: GC overhead limit exceeded
[ant:javac]     at lombok.javac.JavacAST.drill(JavacAST.java:363)
[ant:javac]     at lombok.javac.JavacAST.buildStatementOrExpression(JavacAST.java:324)
[ant:javac]     at lombok.javac.JavacAST.buildExpression(JavacAST.java:308)
[ant:javac]     at lombok.javac.JavacAST.buildLocalVar(JavacAST.java:236)
[ant:javac]     at lombok.javac.JavacAST.buildStatementOrExpression(JavacAST.java:319)
[ant:javac]     at lombok.javac.JavacAST.buildStatement(JavacAST.java:312)
[ant:javac]     at lombok.javac.JavacAST.buildMethod(JavacAST.java:293)
[ant:javac]     at lombok.javac.JavacAST.buildType(JavacAST.java:215)
[ant:javac]     at lombok.javac.JavacAST.buildCompilationUnit(JavacAST.java:196)
[ant:javac]     at lombok.javac.JavacAST.<init>(JavacAST.java:85)
[ant:javac]     at lombok.javac.JavacTransformer.transform(JavacTransformer.java:73)
[ant:javac]     at lombok.javac.apt.LombokProcessor.process(LombokProcessor.java:321)
[ant:javac]     at lombok.core.AnnotationProcessor$JavacDescriptor.process(AnnotationProcessor.java:151)
[ant:javac]     at lombok.core.AnnotationProcessor.process(AnnotationProcessor.java:201)
[ant:javac]     at lombok.launch.AnnotationProcessorHider$AnnotationProcessor.process(AnnotationProcessor.java:99)
[ant:javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
[ant:javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
[ant:javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
[ant:javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
[ant:javac]     at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
[ant:javac]     at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
[ant:javac]     at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
[ant:javac]     at com.sun.tools.javac.main.Main.compile(Main.java:523)
[ant:javac]     at com.sun.tools.javac.main.Main.compile(Main.java:381)
[ant:javac]     at com.sun.tools.javac.main.Main.compile(Main.java:370)
[ant:javac]     at com.sun.tools.javac.main.Main.compile(Main.java:361)
[ant:javac]     at com.sun.tools.javac.Main.compile(Main.java:56)
[ant:javac]     at com.sun.tools.javac.Main.main(Main.java:42)
:compile (Thread[Task worker for ':',5,main]) completed. Took 3 mins 12.565 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compile'.
> The following error occurred while executing this line:
  C:\oo\dev\ac\build\ivy-build-functions.xml:435: The following error occurred while executing this line:
  C:\oo\dev\ac\build\ivy-build-functions.xml:422: Compile failed; see the compiler error output for details.

* Try:
Run with --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':compile'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:103)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:73)
        at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
        at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:256)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:249)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:238)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:663)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:597)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: C:\oo\dev\ac\build\ivy-build-functions.xml:297: The following error occurred while executing this line:
C:\oo\dev\ac\build\ivy-build-functions.xml:435: The following error occurred while executing this line:
C:\oo\dev\ac\build\ivy-build-functions.xml:422: Compile failed; see the compiler error output for details.
        at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:575)
        at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:405)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.Target.execute(Target.java:435)
        at org.apache.tools.ant.Target.performTasks(Target.java:456)
        at org.gradle.api.tasks.ant.AntTarget.executeAntTarget(AntTarget.java:38)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:788)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:755)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:124)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
        at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:113)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:95)
        ... 30 more
Caused by: C:\oo\dev\ac\build\ivy-build-functions.xml:435: The following error occurred while executing this line:
C:\oo\dev\ac\build\ivy-build-functions.xml:422: Compile failed; see the compiler error output for details.
        at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:575)
        at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:405)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:402)
        ... 49 more
Caused by: C:\oo\dev\ac\build\ivy-build-functions.xml:422: Compile failed; see the compiler error output for details.
        at org.apache.tools.ant.taskdefs.Javac.compile(Javac.java:1416)
        at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:1121)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.apache.tools.ant.Task.perform(Task.java:348)
        at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:402)
        ... 57 more

Our expectations where that no OOME occurs.

rspilker commented 5 years ago

How big is the source file? If it's "small", can you post it? Or at least have a small program that demonstrates the problem?

Is there anything special about the code? For example, do you have an enum with 5 billion values?

dmuatdbh commented 5 years ago

Thanx for your answer. We want to compile *.java source with a size of 98MB. That is just our source dir. Additionally we use external libraries with a size of 190MB in all.

There is nothing special about our source code. The biggest java file has a size of 116KB. I can't post our source files, but I will build a dummy project that comes as close to the original as possible (amout of files and external dependencies) and post that one, if the OOME is repeatable.

dmuatdbh commented 5 years ago

Hello @rspilker,

I managed to reproduce the OOME in a small Programm. You can clone the repo from here. Just open the pom.xml in your IDE and run the main from the ClassGenerator.java. That will generate a bunch of files with apache freemarker. The files use the @Getter and @Setter Anotations from lombok. If you compile all these newly generated files, you'll get the Error.

If I write the getter and setter myself without using lombok, I don't get the OutOfMemoryError while compiling all files.

I hope it'll help you to unterstand the problem.

Thank you.

dmuatdbh commented 4 years ago

Has anybody got an idea how to handle this problem? Or might has the same problem? Our stakeholders, that use our framework can't compile our sources without running into tha OutOfMemoryError.

Rawi01 commented 4 years ago

I will look into it, I already have an idea what might cause this problem

Rawi01 commented 4 years ago

Small update:

Can you try to compile it using Java 14? I will create a PR to fix the first issue I found, that might be useful too.

randakar commented 4 years ago

Nice work :)

On Wed, Jul 8, 2020 at 10:53 AM Rawi01 notifications@github.com wrote:

Small update:

  • After looking at some heap dumps I think there is a bug in javac 8, it creates millions of additional ImportScope objects for every annotation processing round. This is gone away using java 14 so most likely they have already fixed that problem. Simply switching to a newer compiler version might solve your problem.
  • asts in JavacTransformer can be removed completly, it does not make sense to keep all asts in memory.
  • WeakHashMaps in JavacAugments, even if these maps are weak they never get cleaned up because the keys are parts of the compilation unit. That means that these maps require additional memory just by keeping milions of references. It might be possible to clean up them by hand at some point but this requires some bigger refactoring.

Can you try to compile it using Java 14? I will create a PR to fix the first issue I found, that might be useful too.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rzwitserloot/lombok/issues/2240#issuecomment-655385179, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABIERITXQDXV3ZVMXXSSOLR2QXYHANCNFSM4IX62MBQ .

-- "Don't only practice your art, but force your way into it's secrets, for it and knowledge can raise men to the divine." -- Ludwig von Beethoven

dmuatdbh commented 4 years ago

When compiling with Java 14, the OutOfMemoryError has gone. Thank you for that hint. As we will compile with Java 8 for a while, your fix might help us in the meantime.

Rawi01 commented 4 years ago

I am not sure if this change will really help in this case, the javac problem consumes way more memory. Is there a specific reason you have to use an old compiler? IIRC you can compile for an older Java version using a modern compiler without any problems.

rspilker commented 4 years ago

@dmuatdbh Could you switch to using the java 14 compiler to generate java 8 class files? Or won't the code or some dependencies not even compile using a more modern version of java?

dmuatdbh commented 4 years ago

Thank you both for your fast reply. This is exactly the problem. We are still using dependencies from the com.sun-package, that won't compile in this case. Anyhow, we should get rid of it and then compile with a Java 14 compiler.

dmuatdbh commented 4 years ago

Just a short feedback. In a (locally built) lombok.jar with the fixes in the JavacTransformer (master-branch) the OutOfMemoryError remains. The solution ist to compile with JAVA 14.

debraj-manna commented 3 years ago

@dmuatdbh - Is JAVA 14 the minimum version needed or JAVA 11 will also work ?

dmuatdbh commented 3 years ago

Yes, only the JAVA 14 compiler in combination with the fix in Lombok (see former post) could solve our problem.

anurparaora commented 2 years ago

Checking if this problem was addressed in Java 8. If not, does this work in Java 11?

dmuatdbh commented 2 years ago

Yes, compiling a huge amount of Files with JAVA 8, using Lombok, you might get this Error. Compiling with JAVA 14 the Error is gone. I don't know, if it is gone using JAVA 11.

debraj-manna commented 2 years ago

It was not working with Java 11 when I tried last time about a year back.