Community
Participate
Working Groups
Created attachment 273004 [details] JMH and its dependencies in one jar Since roughly ECJ 4.7.2, we are seeing a NoClassDefFoundError when using an annotation processor from JMH[1]. This should be reproducible with the following TestJMH_1_18 class: ---- package test.jmh_1_18; import org.openjdk.jmh.annotations.*; @Warmup(iterations = 2) @Measurement(iterations = 2) @Fork(2) public class TestJMH_1_18 { @Benchmark @BenchmarkMode(Mode.All) public void testJMH() { } } ---- rm -rf bin; java -jar ecj-4.8M5.jar -cp jmh-all.jar -nowarn -d bin -processorpath jmh-all.jar -source 1.8 TestJMH_1_18.java ---------- 1. ERROR in /Users/dsimon/fff/test/jmh_1_18/generated/TestJMH_1_18_testJMH_jmhTest.java (at line 0) package test.jmh_1_18.generated; ^ Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError: org/openjdk/jmh/runner/BenchmarkListEntry at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:169) ---------- 1 problem (1 error) rm -rf bin; java -jar ecj-4.5.1.jar -cp jmh-all.jar -nowarn -d bin -processorpath jmh-all.jar -source 1.8 TestJMH_1_18.java [1] http://openjdk.java.net/projects/code-tools/jmh/
I ran into this as well with Tycho 1.2.0
Any chance of this getting some attention? It's preventing the Graal project from supporting development on recent versions of Eclipse.
I can reproduce with ecj starting from 4.7.2 and 4.8M3. It fails in this stack (running JDT HEAD on JDK-9 in this case): URLClassPath.getLoader(int) line: 352 URLClassPath.getResource(String, boolean) line: 243 URLClassLoader$1.run() line: 450 URLClassLoader$1.run() line: 447 AccessController.doPrivileged(PrivilegedExceptionAction<T>, AccessControlContext) line: not available [native method] URLClassLoader.findClass(String) line: 446 URLClassLoader(ClassLoader).loadClass(String, boolean) line: 563 URLClassLoader(ClassLoader).loadClass(String) line: 496 BenchmarkGenerator.complete(GeneratorSource, GeneratorDestination) line: 132 BenchmarkProcessor.process(Set<TypeElement>, RoundEnvironment) line: 59 RoundDispatcher.handleProcessor(ProcessorInfo) line: 142 RoundDispatcher.round() line: 113 BatchAnnotationProcessorManager(BaseAnnotationProcessorManager).processAnnotations(CompilationUnitDeclaration[], ReferenceBinding[], boolean) line: 171 Compiler.processAnnotations() line: 978 Compiler.compile(ICompilationUnit[], boolean) line: 450 Compiler.compile(ICompilationUnit[]) line: 426 Main.performCompilation() line: 4704 Main.compile(String[]) line: 1768 Main.main(String[]) line: 1491 Here null is returned because URLClassPath.closed == true; Closing happens in this call stack: URLClassPath.closeLoaders() line: 166 URLClassLoader.close() line: 376 BatchAnnotationProcessorManager.reset() line: 263 Compiler.processAnnotations() line: 967 Compiler.compile(ICompilationUnit[], boolean) line: 450 Compiler.compile(ICompilationUnit[]) line: 426 Main.performCompilation() line: 4704 Main.compile(String[]) line: 1768 Main.main(String[]) line: 1491 This doesn't look awfully suspicious, if you ask me... Note, that here: Compiler.compile(ICompilationUnit[], boolean) line: 450 we have a flag 'lastRound'. Should that be passed down so we this.annotationProcessorManager.reset() only for the last round?? Or is some of the reset() work needed between rounds? Is that enough information for you to proceed?
*** Bug 547171 has been marked as a duplicate of this bug. ***
The suspicious close() was added via https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA9&id=0171d3fa20410a884ea6de07ec393bc179fb73bd
(In reply to Stephan Herrmann from comment #3) > Should that be passed down so we this.annotationProcessorManager.reset() > only for the last round?? Or is some of the reset() work needed between > rounds? Thanks Stephan, for the investigation. The reset() is certainly needed between rounds, mostly for what we in super.reset(), but we need to find a way to do the close() only at the end of final round. I need to see if this information is already passed to the BaseAnnotationProcessorManager.
(In reply to Jay Arthanareeswaran from comment #6) > Thanks Stephan, for the investigation. The reset() is certainly needed > between rounds, mostly for what we in super.reset(), but we need to find a > way to do the close() only at the end of final round. I need to see if this > information is already passed to the BaseAnnotationProcessorManager. On closer look, this may not be sufficient. The "lastRound" in the compiler doesn't necessarily mean there won't be another round as the annotation processors can still generate more files triggering compilation. Perhaps, we can check for newly added units and classes and if none then invoke close(). Will see what it takes during 4.13.
Bulk Move Out of 4.13
What's the status here? We're running into this with org.eclipse.jdt:ecj:3.18.0. See also https://github.com/spring-projects/sts4/issues/171, which is exactly the error we're seeing. Note that the AspectJ developer(s) have actually fixed this in their patched ecj version. Unfortunately they include only a zip of the compiler sources in their repo, but: * download https://github.com/eclipse/org.aspectj/blob/2bcf229024608c411d8effa248e63c8742b35508/org.eclipse.jdt.core/jdtcore-for-aspectj-src.zip (their sources before their fix) * download https://github.com/eclipse/org.aspectj/blob/380ef0ec470fcf02820bde4d22d3bd1a9efaf999/org.eclipse.jdt.core/jdtcore-for-aspectj-src.zip (their sources after their fix) Unpack both in different directories and compare to see the I cannot tell whether that way to fix it is complete or sufficient. It goes in the direction that is suggested here. (Delaying closing the classpath.)
(In reply to Thomas Wolf from comment #9) > What's the status here? We're running into this with > org.eclipse.jdt:ecj:3.18.0. Sorry, we couldn't spend time on this as the team is currently busy with the Java 13 work. However, since you have already found the fix, would you be able to bring that fix in the form of a patch? If there's a patch, we will be able to take this to closure sooner.
New Gerrit change created: https://git.eclipse.org/r/149331
(In reply to Eclipse Genie from comment #11) > New Gerrit change created: https://git.eclipse.org/r/149331 There you go. As I wrote above: I have no idea if this way to fix it is sound. Please take over this change. (I also wouldn't know how to write tests for this, and I don't have the time to figure it out.)
(In reply to Thomas Wolf from comment #12) > (In reply to Eclipse Genie from comment #11) > > New Gerrit change created: https://git.eclipse.org/r/149331 > > There you go. As I wrote above: I have no idea if this way to fix it is > sound. Please take over this change. (I also wouldn't know how to write > tests for this, and I don't have the time to figure it out.) Thanks, I slightly modified the patch: - new method shouldn't be abstract, since this left some sub classes without an implementation - renamed the method to speak more about intent (final cleanUp) rather than implementation (close a class loader, which only one subclass actually owns). I manually checked with the steps from comment 0 that this indeed fixes the problem. @Jay: Just like Thomas I'm not sufficiently versed in writing tests for annotation processing. Do you insist in having a test case, or may I push the fix without a test?
(In reply to Stephan Herrmann from comment #13) > @Jay: Just like Thomas I'm not sufficiently versed in writing tests for > annotation processing. Do you insist in having a test case, or may I push > the fix without a test? +1 for the fix without a test. Thanks Stephan and Thomas!
Gerrit change https://git.eclipse.org/r/149331 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=328421a0239051bed525c280adc9937c7a561a78
(In reply to Eclipse Genie from comment #15) > Gerrit change https://git.eclipse.org/r/149331 was merged to [master]. > Commit: > http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/ > ?id=328421a0239051bed525c280adc9937c7a561a78 Released for 4.14 M1 thanks
Verified for Eclipse Version: 2019-12 (4.14) M1 with Build id: I20191008-1800
This might need to be reopened. As far as I can tell, Compiler.processAnnotations() is called into multiple times, so closing after one call is still too premature. Example from Gradle build: Stacktrace where close happens: java.lang.Throwable at java.net.URLClassLoader.close(URLClassLoader.java:288) at org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager.cleanUp(BatchAnnotationProcessorManager.java:264) at org.eclipse.jdt.internal.compiler.Compiler.processAnnotations(Compiler.java:933) at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:450) at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:426) at org.eclipse.jdt.internal.compiler.batch.Main.performCompilation(Main.java:4771) at org.eclipse.jdt.internal.compiler.batch.Main.compile(Main.java:1773) at org.eclipse.jdt.internal.compiler.batch.Main.main(Main.java:1496) Stacktrace where NoClassDefFoundError occurs: java.lang.Throwable at dagger.internal.codegen.DaggerStatisticsCollector.processingStopped(DaggerStatisticsCollector.java:80) at dagger.internal.codegen.ComponentProcessor.postRound(ComponentProcessor.java:188) at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:176) at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:142) at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.round(RoundDispatcher.java:113) at org.eclipse.jdt.internal.compiler.apt.dispatch.BaseAnnotationProcessorManager.processAnnotations(BaseAnnotationProcessorManager.java:171) at org.eclipse.jdt.internal.compiler.Compiler.processAnnotationsInternal(Compiler.java:995) at org.eclipse.jdt.internal.compiler.Compiler.processAnnotations(Compiler.java:931) at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:450) at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:469) at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:426) at org.eclipse.jdt.internal.compiler.batch.Main.performCompilation(Main.java:4771) at org.eclipse.jdt.internal.compiler.batch.Main.compile(Main.java:1773) at org.eclipse.jdt.internal.compiler.batch.Main.main(Main.java:1496) Gradle error: Internal compiler error: java.lang.Exception: java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: dagger/internal/codegen/DaggerStatisticsRecorder at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:172) Tested with ecj batch compiler 4.14 release.
(In reply to Henry Tung from comment #18) > This might need to be reopened. As far as I can tell, > Compiler.processAnnotations() is called into multiple times, so closing > after one call is still too premature. In the Scout project we see this error too. It is less common than before the fix but it still occurs. Possibly moving this.annotationProcessorManager.cleanUp(); to the end of Compiler.compile(ICompilationUnit[] sourceUnits, boolean lastRound) instead of calling it prematurely in Compiler processAnnotations() could work?
New Gerrit change created: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/169633
Scout project here again. I have created a new patch, which will now hopefully fix this issue for us (graalvm and others). I assume the problem is that in case of a SourceTypeCollisionException (with lastRound == false) the new cleanUp method is called prematurely.
(In reply to Ralph Steiner from comment #21) > Scout project here again. I have created a new patch, which will now > hopefully fix this issue for us (graalvm and others). I assume the problem > is that in case of a SourceTypeCollisionException (with lastRound == false) > the new cleanUp method is called prematurely. When you say 'hopefully' and the patch doesn't have a test, it's that much more work for those reviewing :) Will take a look at it this week.
Patch looks alright to me. Something to note: In our entire test suite, there's just one testcase in BuilderTests.testBug468893() that triggers this code.
Gerrit change https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/169633 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=7149a5b706ba5c5fae4e1d1c8a919f79aebbcd6e
Moving back to resolved. Not changing the target, but setting the whiteboard so that this shows in our verification list for 4.18 M1.
Is it possible that because of this change some tests in jdt.ui fail now? There are annotations that now have a newline. Content not as expected: is package test1; import org.eclipse.jdt.annotation.NonNull; public class E { public <T extends Number> double foo(T t) { @NonNull Number n=t; return n.doubleValue(); } } Differs at pos 141: onNull^ expected: package test1; import org.eclipse.jdt.annotation.NonNull; public class E { public <T extends Number> double foo(T t) { @NonNull Number n=t; return n.doubleValue(); } } expected:<...) { @NonNull[] Number n=t; ...> but was:<...) { @NonNull[ ] Number n=t; ...> Could easily be that it is one of our jdt.ui gerrits that is responsible but just want to be sure and don't understand this right now...
(In reply to Carsten Hammer from comment #26) > Is it possible that because of this change some tests in jdt.ui fail now? > There are annotations that now have a newline. > ... > Could easily be that it is one of our jdt.ui gerrits that is responsible but > just want to be sure and don't understand this right now... I highly doubt that. This change does nothing to alter the annotations. Hypothetically, it's possible that this fixed some annotation processor that is producing a different result now. But chances are very slim.
Verified for 4.18 m1 Version: 2020-12 (4.18) Build id: I20200928-1800 [by code walkthrough]