Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoClassDefFoundError: javax/annotation/Generated on Java 9 #560

Closed
davido opened this issue Dec 5, 2017 · 7 comments
Closed

NoClassDefFoundError: javax/annotation/Generated on Java 9 #560

davido opened this issue Dec 5, 2017 · 7 comments
Assignees

Comments

@davido
Copy link

davido commented Dec 5, 2017

//CC @cushon

This is the very first time, I'm trying to build Gerrit Code Review with Bazel, with Java 9. We have this Bazel patch: hhclam/bazel@64212c8.

One issue is EP doesn't really work with mentioned Bazel patch, the vanilla javac is used and not the bundled one with Bazel:

ERROR: /home/davido/projects/gerrit2/java/com/google/gerrit/common/BUILD:32:1: Building java/com/google/gerrit/common/libserver.jar (57 source files) failed (Exit 1)
java/com/google/gerrit/common/RawInputUtil.java:34: error: [CheckReturnValue] Ignored return value of method that is annotated with @CheckReturnValue
    Preconditions.checkNotNull(bytes);
                              ^
    (see http://errorprone.info/bugpattern/CheckReturnValue)
  Did you mean to remove this line?
[...]
ERROR: /home/davido/projects/gerrit2/java/com/google/gerrit/util/cli/BUILD:1:1: Building java/com/google/gerrit/util/cli/libcli.jar (6 source files) failed (Exit 1)
java/com/google/gerrit/util/cli/CmdLineParser.java:229: error: [CheckReturnValue] Ignored return value of method that is annotated with @CheckReturnValue
        map.put(ent.getKey(), val);
               ^
    (see http://errorprone.info/bugpattern/CheckReturnValue)
  Did you mean to remove this line?
Target //java/com/google/gerrit/server:server failed to build

EP can be disabled for now, using: --javacopt="-XepDisableAllChecks" option.

Gerrit issue, is outdated auto-value version used (1.4.1). That's because the auto-value upgrade had to be reverted due to Eclipse-Oxygen bug, that was fixed meantime, but wasn't released yet.

Auto-value is upgraded with this diff (applied on gerrit master):

diff --git a/WORKSPACE b/WORKSPACE
index 6810f79c93..4f5de9b620 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -408,8 +408,8 @@ maven_jar(
 
 maven_jar(
     name = "auto_value",
-    artifact = "com.google.auto.value:auto-value:1.4.1",
-    sha1 = "8172ebbd7970188aff304c8a420b9f17168f6f48",
+    artifact = "com.google.auto.value:auto-value:1.5.2",
+    sha1 = "1b94ab7ec707e2220a0d1a7517488d1843236345",
 )
 
 maven_jar(

With these three fixes:

  • Custom Bazel build
  • Disabled EP
  • Auto-Value upgrade to 1.5.2

trying to build java/com/google/gerrit/sshd:sshd on Java 9 is failing with:

$ /home/davido/projects/bazel/bazel-bin/src/bazel build java/com/google/gerrit/sshd:sshd --javacopt="-XepDisableAllChecks" --host_java_toolchain=@bazel_tools//tools/jdk:jdk9 --java_toolchain=@bazel_tools//tools/jdk:jdk9
INFO: Analysed target //java/com/google/gerrit/sshd:sshd (0 packages loaded).
INFO: Found 1 target...
ERROR: /home/davido/projects/gerrit/java/com/google/gerrit/sshd/BUILD:1:1: Building java/com/google/gerrit/sshd/libsshd.jar (97 source files) and running annotation processors (AutoAnnotationProcessor, AutoValueProcessor) failed (Exit 1)
java.lang.RuntimeException: java.lang.NoClassDefFoundError: javax/annotation/Generated
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:158)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
	at com.google.devtools.build.buildjar.javac.BlazeJavacMain.compile(BlazeJavacMain.java:107)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder$1.invokeJavac(SimpleJavaLibraryBuilder.java:105)
	at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.compileSources(ReducedClasspathJavaLibraryBuilder.java:54)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.compileJavaLibrary(SimpleJavaLibraryBuilder.java:108)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.run(SimpleJavaLibraryBuilder.java:116)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.processRequest(BazelJavaBuilder.java:105)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.runPersistentWorker(BazelJavaBuilder.java:67)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.main(BazelJavaBuilder.java:45)
Caused by: java.lang.NoClassDefFoundError: javax/annotation/Generated
	at com.google.auto.value.processor.AutoAnnotationProcessor.getReferencedTypes(AutoAnnotationProcessor.java:450)
	at com.google.auto.value.processor.AutoAnnotationProcessor.processMethod(AutoAnnotationProcessor.java:152)
	at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:129)
	at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:113)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:968)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:884)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.access$2200(JavacProcessingEnvironment.java:108)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1206)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1315)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1246)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
	... 10 more
Caused by: java.lang.ClassNotFoundException: javax.annotation.Generated
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:466)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:563)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
	... 23 more
Target //java/com/google/gerrit/sshd:sshd failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.626s, Critical Path: 0.43s
FAILED: Build did NOT complete successfully

Environment: Linux.

$ java -version
openjdk version "9.0.1"
@davido
Copy link
Author

davido commented Dec 5, 2017

I went ahead and added 'javax.annotation:javax.annotation-api:jar:1.3.1' to Gerrit with this patch: [1]. Now I'm getting a different error:

$ /home/davido/projects/bazel/bazel-bin/src/bazel build java/com/google/gerrit/sshd:sshd  --javacopt="-XepDisableAllChecks" --host_java_toolchain=@bazel_tools//tools/jdk:jdk9 --java_toolchain=@bazel_tools//tools/jdk:jdk9
INFO: Analysed target //java/com/google/gerrit/sshd:sshd (1 packages loaded).
INFO: Found 1 target...
ERROR: /home/davido/projects/gerrit/java/com/google/gerrit/sshd/BUILD:1:1: Building java/com/google/gerrit/sshd/libsshd.jar (97 source files) and running annotation processors (AutoAnnotationProcessor, AutoValueProcessor) failed (Exit 1)
java/com/google/gerrit/sshd/Commands.java:48: error: @AutoAnnotation processor threw an exception: java.lang.NullPointerException
  public static CommandName named(String value) {
                            ^
  	at com.google.auto.value.processor.AutoAnnotationProcessor.getTypeMirror(AutoAnnotationProcessor.java:470)
  	at com.google.auto.value.processor.AutoAnnotationProcessor.getReferencedTypes(AutoAnnotationProcessor.java:450)
  	at com.google.auto.value.processor.AutoAnnotationProcessor.processMethod(AutoAnnotationProcessor.java:152)
  	at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:129)
  	at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:113)
  	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:968)
  	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:884)
  	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.access$2200(JavacProcessingEnvironment.java:108)
  	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1206)
  	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1315)
  	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1246)
  	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
  	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
  	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
  	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
  	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
  	at com.google.devtools.build.buildjar.javac.BlazeJavacMain.compile(BlazeJavacMain.java:107)
  	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder$1.invokeJavac(SimpleJavaLibraryBuilder.java:105)
  	at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.compileSources(ReducedClasspathJavaLibraryBuilder.java:54)
  	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.compileJavaLibrary(SimpleJavaLibraryBuilder.java:108)
  	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.run(SimpleJavaLibraryBuilder.java:116)
  	at com.google.devtools.build.buildjar.BazelJavaBuilder.processRequest(BazelJavaBuilder.java:105)
  	at com.google.devtools.build.buildjar.BazelJavaBuilder.runPersistentWorker(BazelJavaBuilder.java:67)
  	at com.google.devtools.build.buildjar.BazelJavaBuilder.main(BazelJavaBuilder.java:45)
java.lang.RuntimeException: java.lang.NullPointerException
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:158)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:96)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:90)
	at com.google.devtools.build.buildjar.javac.BlazeJavacMain.compile(BlazeJavacMain.java:107)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder$1.invokeJavac(SimpleJavaLibraryBuilder.java:105)
	at com.google.devtools.build.buildjar.ReducedClasspathJavaLibraryBuilder.compileSources(ReducedClasspathJavaLibraryBuilder.java:54)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.compileJavaLibrary(SimpleJavaLibraryBuilder.java:108)
	at com.google.devtools.build.buildjar.SimpleJavaLibraryBuilder.run(SimpleJavaLibraryBuilder.java:116)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.processRequest(BazelJavaBuilder.java:105)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.runPersistentWorker(BazelJavaBuilder.java:67)
	at com.google.devtools.build.buildjar.BazelJavaBuilder.main(BazelJavaBuilder.java:45)
Caused by: java.lang.NullPointerException
	at com.google.auto.value.processor.AutoAnnotationProcessor.getTypeMirror(AutoAnnotationProcessor.java:470)
	at com.google.auto.value.processor.AutoAnnotationProcessor.getReferencedTypes(AutoAnnotationProcessor.java:450)
	at com.google.auto.value.processor.AutoAnnotationProcessor.processMethod(AutoAnnotationProcessor.java:152)
	at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:129)
	at com.google.auto.value.processor.AutoAnnotationProcessor.process(AutoAnnotationProcessor.java:113)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:968)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:884)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.access$2200(JavacProcessingEnvironment.java:108)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1206)
	at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1315)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1246)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:100)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:142)
	... 10 more
Target //java/com/google/gerrit/sshd:sshd failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 18.535s, Critical Path: 18.33s
FAILED: Build did NOT complete successfully

[1] http://paste.openstack.org/show/628224

@davido
Copy link
Author

davido commented Dec 6, 2017

The NPE seems to be related to the patched Bazel version. I extracted this reproducer from gerrit Code Review project and verified that auto-value just worked with Maven, but failing with NPE with Bazel.

@cushon
Copy link
Contributor

cushon commented Dec 6, 2017

The part of this that is an auto bug is that AutoAnnotationProcessor should be using something like c9fd48f instead of trying to load javax.annotatation.Generated here:

That avoids the need for an explicit dep on javax.annotation.Generated, and fixes:

Caused by: java.lang.NoClassDefFoundError: javax/annotation/Generated
	at com.google.auto.value.processor.AutoAnnotationProcessor.getReferencedTypes(AutoAnnotationProcessor.java:450)

The other NPE:

Caused by: java.lang.NullPointerException
	at com.google.auto.value.processor.AutoAnnotationProcessor.getTypeMirror(AutoAnnotationProcessor.java:470)
	at com.google.auto.value.processor.AutoAnnotationProcessor.getReferencedTypes(AutoAnnotationProcessor.java:450)

... appears to be because the patch to gerrit and the repro at davido/ostrovsky add javax-annotation to the processor classpath, but not the compilation classpath. (I'm not sure maven makes that distinction, which might be why it works?) Anyway, exporting javax-annotation from the auto-value target avoids the NPE:

diff --git a/lib/BUILD b/lib/BUILD
index 242d328..39eaabf 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -28,5 +28,8 @@ java_library(
         ":auto-value-plugin",
     ],
     visibility = ["//visibility:public"],
-    exports = ["@auto_value//jar"],
+    exports = [
+        ":javax-annotation",
+        "@auto_value//jar",
+    ],
 )

@tbroyer
Copy link
Contributor

tbroyer commented Dec 6, 2017

I'm not sure maven makes that distinction, which might be why it works?

Maven can make the distinction (https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#annotationProcessorPaths) but the repro case here does not use the processor classpath (i.e. annotation processors are looked up in the compilation classpath).
So I would say this is why it works.

@davido
Copy link
Author

davido commented Dec 6, 2017

@cushon Thanks. It was too early today morning. I can build GWT UI based gerrit on Java 9 now. JS stack is still failing with Dagger related stuff, used by rules_closure, reported here [1].

Even more interesting, if I try to install gerrit.war, that was built with Java 9, I'm running into NPE:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.google.gerrit.server.index.change.ChangeSchemaDefinitions.<clinit>(ChangeSchemaDefinitions.java:25)
	at com.google.gerrit.server.index.IndexModule.<clinit>(IndexModule.java:78)
	at com.google.gerrit.pgm.init.InitIndex.run(InitIndex.java:69)
	at com.google.gerrit.pgm.init.SitePathInitializer.run(SitePathInitializer.java:93)
	at com.google.gerrit.pgm.init.BaseInit.run(BaseInit.java:138)
	at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:204)
	at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:109)
	at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:64)
	at Main.main(Main.java:24)
Caused by: java.lang.NullPointerException: Null rule
	at com.google.gerrit.server.project.AutoValue_SubmitRuleOptions$Builder.rule(AutoValue_SubmitRuleOptions.java:102)
	at com.google.gerrit.server.project.SubmitRuleOptions.builder(SubmitRuleOptions.java:32)
	at com.google.gerrit.server.index.change.ChangeField.<clinit>(ChangeField.java:566)
	... 14 more

Well, looking at the auto-value generated code where the above exception is thrown:

    @Override
    public SubmitRuleOptions.Builder rule(String rule) {
      if (rule == null) {
        throw new NullPointerException("Null rule");
      }
      this.rule = rule;
      return this;
    }

I would need to look deeper, what is going on there.

@davido
Copy link
Author

davido commented Dec 8, 2017

@cushon Thanks for the pointer.

The part of this that is an auto bug is that AutoAnnotationProcessor should be using something like c9fd48f instead of trying to load javax.annotatation.Generated here:

I was able to replace this hard coded part with:

diff --git a/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java b/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java
index 4a7780d..0d68f95 100644
--- a/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java
+++ b/value/src/main/java/com/google/auto/value/processor/AutoAnnotationProcessor.java
@@ -17,6 +17,7 @@ package com.google.auto.value.processor;
 
 import static java.util.stream.Collectors.toCollection;
 
+import com.google.auto.common.GeneratedAnnotations;
 import com.google.auto.common.MoreElements;
 import com.google.auto.common.SuperficialValidation;
 import com.google.auto.service.AutoService;
@@ -35,7 +36,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
-import javax.annotation.Generated;
 import javax.annotation.processing.AbstractProcessor;
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.annotation.processing.Processor;
@@ -191,12 +191,12 @@ public class AutoAnnotationProcessor extends AbstractProcessor {
   }
 
   private String getGeneratedTypeName(TypeSimplifier typeSimplifier) {
-    TypeElement generatedTypeElement =
-        processingEnv.getElementUtils().getTypeElement("javax.annotation.Generated");
-    if (generatedTypeElement == null) {
+    Optional<TypeElement> generatedTypeElement =
+        GeneratedAnnotations.generatedAnnotation(processingEnv.getElementUtils());
+    if (!generatedTypeElement.isPresent()) {
       return "";
     }
-    return typeSimplifier.simplify(generatedTypeElement.asType());
+    return typeSimplifier.simplify(generatedTypeElement.get().asType());
   }
 
   /**

But, in the same compilation unit we have also this usage of: javax.annotation.Generated, thta should be eliminated:

  private Set<TypeMirror> getReferencedTypes(
      TypeMirror annotation,
      ExecutableElement method,
      Set<TypeMirror> memberTypes,
      Set<Class<?>> wrapperTypesUsedInCollections) {
    Set<TypeMirror> types = new TypeMirrorSet();
    types.add(annotation);
    types.add(getTypeMirror(Generated.class));
[...]

Just guessing:

-  types.add(getTypeMirror(Generated.class));
+  types.add(GeneratedAnnotations.generatedAnnotation(processingEnv.getElementUtils()).get().asType());

@davido
Copy link
Author

davido commented Dec 16, 2017

Seems to be fixed with: f04406c.

@davido davido closed this as completed Dec 16, 2017
lucamilanesio pushed a commit to GerritCodeReview/gerrit that referenced this issue Feb 8, 2018
We need to upgrade rules_closure tools to be able to build with Java 9.
That's because rules_closure depends on dagger 2 and auto-common and
auto-value, that need to be updated to not depend on legacy annotations
(that are not available on Java 9). Moreover, latest rules_closure
switched to building protobuf library from the sources, creating the
next problem: Protobuf doesn't support Java 9 yet. That was fixed only
on master, so that we need to update rules_closure to consume the
protobuf dependency from HEAD.

See these issues for more background: [1],[2],[3],[4].

[1] google/auto#560
[2] bazelbuild/rules_closure#234
[3] google/dagger#880
[4] protocolbuffers/protobuf#4256

Bug: Issue 7958
Change-Id: I56f3b6101e06bd678b4e42d3a9d52157963513aa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants