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

java.lang.ExceptionInInitializerError in AutoValueSubclassLeaked caused by NullPointerException in Caffeine #1986

Closed
sjamesr opened this issue Dec 5, 2020 · 6 comments · Fixed by #1993
Assignees

Comments

@sjamesr
Copy link

sjamesr commented Dec 5, 2020

I'm getting the following crash inside error-prone on Java 8. Works fine on Java 11. It's not urgent for me, I'm happy to not support building on Java 8 at this point.

     error-prone version: 2.4.0
     BugPattern: AutoValueSubclassLeaked
     Stack Trace:
     java.lang.ExceptionInInitializerError
        at com.google.errorprone.bugpatterns.AutoValueSubclassLeaked$1.handle(AutoValueSubclassLeaked.java:83)
        at com.google.errorprone.bugpatterns.AutoValueSubclassLeaked$1.visitMemberSelect(AutoValueSubclassLeaked.java:72)
        at com.google.errorprone.bugpatterns.AutoValueSubclassLeaked$1.visitMemberSelect(AutoValueSubclassLeaked.java:69)
        at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:2112)
    <snip>
      Caused by: java.lang.NullPointerException
        at com.github.benmanes.caffeine.cache.LocalCacheFactory.newBoundedLocalCache(LocalCacheFactory.java:95)
        at com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache.<init>(BoundedLocalCache.java:3392)
        at com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache.<init>(BoundedLocalCache.java:3388)
        at com.github.benmanes.caffeine.cache.Caffeine.build(Caffeine.java:988)
        at com.google.errorprone.util.ASTHelpers.<clinit>(ASTHelpers.java:722)
        ... 66 more

To reproduce

Make sure OpenJDK 8 is available in JAVA_HOME, this example assumes it's in /usr/lib/java-8-openjdk-amd64/.

$ git clone [email protected]:sjamesr/jfreesane.git
$ cd jfreesane
$ git fetch origin pull/102/head
$ git checkout FETCH_HEAD
$ JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ ./gradlew check

What version of Error Prone are you using?

2.4.0, invoked by net.ltgt.errorprone plugin version 1.3.0.

Have you found anything relevant by searching the web?

No luck.

sjamesr added a commit to sjamesr/jfreesane that referenced this issue Dec 5, 2020
error-prone plugin
[crashes](200~google/error-prone#1986) on Java
8, for that reason we remove Java 8 from the Travis-CI configuration.
sjamesr added a commit to sjamesr/jfreesane that referenced this issue Dec 5, 2020
error-prone plugin
[crashes](google/error-prone#1986) on Java
8, for that reason we remove Java 8 from the Travis-CI configuration.
@cushon
Copy link
Collaborator

cushon commented Dec 7, 2020

With

diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java
index a368046d..345ef392 100644
--- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java
+++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java
@@ -99,7 +99,7 @@ public final class LocalCacheSelectorCode {
   private LocalCacheSelectorCode selector() {
     block
         .beginControlFlow("try")
-            .addStatement("$T<?> clazz = $T.class.getClassLoader().loadClass(sb.toString())",
+            .addStatement("$T<?> clazz = java.util.Objects.requireNonNull($T.class.getClassLoader(), \"oh no\").loadClass(sb.toString())",
                 Class.class, LOCAL_CACHE_FACTORY)
             .addStatement("$T<?> ctor = clazz.getDeclaredConstructor($T.class, $T.class, $T.class)",
                 Constructor.class, BUILDER, CACHE_LOADER.rawType, TypeName.BOOLEAN)

I see

$ ./gradlew check --debug
...
[INFO] [org.gradle.workers.internal.WorkerDaemonStarter] Started Gradle worker daemon (0.326 secs) with fork options DaemonForkOptions{..., jvmArgs=[-Xbootclasspath/p:...caffeine-2.8.8-SNAPSHOT.jar...
...
[INFO] [org.gradle.api.internal.tasks.compile.JdkJavaCompiler] Compiling with JDK Java compiler API.
[ERROR] [system.err] ./jfreesane/src/main/java/au/com/southsky/jfreesane/package-info.java:10: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
[ERROR] [system.err] package au.com.southsky.jfreesane;
[ERROR] [system.err] ^
[ERROR] [system.err]      Please report this at https://github.com/google/error-prone/issues/new and include the following:
[ERROR] [system.err]
[ERROR] [system.err]      error-prone version: 2.4.1-SNAPSHOT
[ERROR] [system.err]      BugPattern: AutoValueSubclassLeaked
[ERROR] [system.err]      Stack Trace:
[ERROR] [system.err]      java.lang.ExceptionInInitializerError
[ERROR] [system.err]       at com.google.errorprone.bugpatterns.AutoValueSubclassLeaked$1.handle(AutoValueSubclassLeaked.java:83)
[ERROR] [system.err]       at com.google.errorprone.bugpatterns.AutoValueSubclassLeaked$1.visitMemberSelect(AutoValueSubclassLeaked.java:72)
...
[ERROR] [system.err]   Caused by: java.lang.NullPointerException: oh no
[ERROR] [system.err]       at java.util.Objects.requireNonNull(Objects.java:228)
[ERROR] [system.err]       at com.github.benmanes.caffeine.cache.LocalCacheFactory.newBoundedLocalCache(LocalCacheFactory.java:88)

I reported this against caffeine as ben-manes/caffeine#481

I'm not sure why gradle is using -Xbootclasspath/p: there, having caffeine on the regular classpath should avoid the crash. With JDK 8, Error Prone expects error-prone-javac to be on the bootclasspath, but everything else can be on the regular classpath. Maybe the gradle plugin is just putting everything on the bootclasspath?

@sjamesr
Copy link
Author

sjamesr commented Dec 8, 2020

Thanks for taking a look. I dug into the Error Prone gradle plugin a little bit (which you can debug directly from intellij, kinda nice), see https://github.com/tbroyer/gradle-errorprone-plugin/blob/master/src/main/kotlin/net/ltgt/gradle/errorprone/ErrorPronePlugin.kt#L87

        fun JavaCompile.configureErrorProneJavac() {
            if (!options.isFork) {
                options.isFork = true
                // reset forkOptions in case they were configured
                options.forkOptions = ForkOptions()
            }
            javacConfiguration.asPath.also {
                if (it.isNotBlank()) {
                    options.forkOptions.jvmArgs!!.add("-Xbootclasspath/p:$it")    // error prone and caffeine added to bootclasspath
                } else if (noJavacDependencyNotified.compareAndSet(false, true)) {
                    LOGGER.warn(NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
                }
            }
        }

There is code further down in the plugin that does this only for Java 8:

                        JavaVersion.current().isJava8 && (!options.isFork || (options.forkOptions.javaHome == null && options.forkOptions.executable == null)) ->
                            configureErrorProneJavac()

Is this a problem with the plugin, or should Caffeine be able to operate in this mode?

@cushon
Copy link
Collaborator

cushon commented Dec 8, 2020

Thanks for investigating!

@tbroyer FYI

Is this a problem with the plugin, or should Caffeine be able to operate in this mode?

Maybe kinda both? :) Ideally Caffeine would work in this mode, but if it's possible for the plugin to only put the error-prone-javac artifact on the boothclasspath, and not all of Error Prone, that's probably worthwhile too.

@ben-manes
Copy link

Thank you for the bug report. Please upgrade caffeine to 2.8.8 to resolve this issue.

@cushon cushon self-assigned this Dec 8, 2020
copybara-service bot pushed a commit that referenced this issue Dec 8, 2020
Fixes #1986

PiperOrigin-RevId: 346253137
copybara-service bot pushed a commit that referenced this issue Dec 8, 2020
Fixes #1986

PiperOrigin-RevId: 346253137
@tbroyer
Copy link
Contributor

tbroyer commented Dec 10, 2020

The Gradle plugin will only put on the bootclasspath the dependencies declared in the errorproneJavac configuration, which should only be com.google.errorprone:javac if you configured your project correctly. ErrorProne (error_prone_core) and its dependencies (including Caffeine) should only be configured in the errorprone configuration, which is only added to the annotation processor path; and this is indeed not what was done here:
https://github.com/sjamesr/jfreesane/blob/da772013bdc45f11c0e7111a1a77684d9075ddf3/build.gradle#L35-L36

This should be

    errorprone 'com.google.errorprone:error_prone_core:2.3.3'
    errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'

@sjamesr
Copy link
Author

sjamesr commented Dec 11, 2020

Aha, thank you!

sjamesr added a commit to sjamesr/jfreesane that referenced this issue Dec 11, 2020
error-prone plugin
[crashes](google/error-prone#1986) on Java
8, for that reason we remove Java 8 from the Travis-CI configuration.
stevie400 pushed a commit to HubSpot/error-prone that referenced this issue Jan 15, 2021
Fixes google#1986

PiperOrigin-RevId: 346387889
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

Successfully merging a pull request may close this issue.

4 participants