NullAway初始化断言错误排查:无法检测Java空指针异常
问题:NullAway初始化失败无法检测NPE
错误栈
java.lang.AssertionError: com.google.errorprone.scanner.ErrorProneInjector$ProvisionException: Failed to initialize com.uber.nullaway.NullAway at com.google.errorprone.ErrorProneAnalyzer.lambda$scansPlugins$0(ErrorProneAnalyzer.java:85) at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:181) at com.google.errorprone.ErrorProneAnalyzer.finished(ErrorProneAnalyzer.java:156) at jdk.compiler/com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:133) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1436) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1383) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:963) at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:319) at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:178) at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:64) at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:50) Caused by: com.google.errorprone.scanner.ErrorProneInjector$ProvisionException: Failed to initialize com.uber.nullaway.NullAway at com.google.errorprone.scanner.ErrorProneInjector.getInstance(ErrorProneInjector.java:92) at com.google.errorprone.scanner.ErrorProneInjector.getInstance(ErrorProneInjector.java:65) at com.google.errorprone.scanner.ScannerSupplierImpl.instantiateChecker(ScannerSupplierImpl.java:66) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:1024) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) at com.google.errorprone.scanner.ScannerSupplierImpl.get(ScannerSupplierImpl.java:74) at com.google.errorprone.scanner.ScannerSupplierImpl.get(ScannerSupplierImpl.java:37) at com.google.errorprone.ErrorProneAnalyzer.lambda$scansPlugins$0(ErrorProneAnalyzer.java:80) ... 10 more Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:74) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) at com.google.errorprone.scanner.ErrorProneInjector.getInstance(ErrorProneInjector.java:90) ... 22 more Caused by: java.lang.NoClassDefFoundError: org/checkerframework/nullaway/dataflow/cfg/node/NodeVisitor at com.uber.nullaway.handlers.Handlers.buildDefault(Handlers.java:67) at com.uber.nullaway.NullAway.<init>(NullAway.java:291) at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) ... 25 more Caused by: java.lang.ClassNotFoundException: org.checkerframework.nullaway.dataflow.cfg.node.NodeVisitor at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:593) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ... 28 more
执行脚本
EP_VERSION=2.23.0 DATAFLOW_VERSION=3.39.0-eisop1 NULLAWAY_VERSION=0.10.15 JSPECIFY_VERSION=1.0.0 # check if downloaded, if not, download error_prone_core_jar=error_prone_core-${EP_VERSION?}-with-dependencies.jar dataflow_errorprone_jar=dataflow-errorprone-${DATAFLOW_VERSION?}.jar nullaway_jar=nullaway-${NULLAWAY_VERSION?}.jar jspecify_jar=jspecify-${JSPECIFY_VERSION?}.jar if [ ! -f $error_prone_core_jar ]; then wget https://repo1.maven.org/maven2/com/google/errorprone/error_prone_core/${EP_VERSION?}/$error_prone_core_jar fi if [ ! -f $dataflow_errorprone_jar ]; then wget https://repo1.maven.org/maven2/io/github/eisop/dataflow-errorprone/${DATAFLOW_VERSION?}/$dataflow_errorprone_jar fi if [ ! -f $nullaway_jar ]; then wget https://repo1.maven.org/maven2/com/uber/nullaway/nullaway/${NULLAWAY_VERSION?}/$nullaway_jar fi if [ ! -f $jspecify_jar ]; then wget https://repo1.maven.org/maven2/org/jspecify/jspecify/${JSPECIFY_VERSION?}/$jspecify_jar fi echo "Jar files downloaded" javac \ -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \ -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \ -XDcompilePolicy=simple \ -cp .:$jspecify_jar \ -processorpath $error_prone_core_jar:$nullaway_jar:$dataflow_errorprone_jar \ '-Xplugin:ErrorProne -XepOpt:NullAway:AnnotatedPackages=com.uber -Xep:CollectionIncompatibleType:ERROR' \ com/uber/mylib/ShortSet.java echo "Compilation finished"
待检测代码(com/uber/mylib/ShortSet.java)
package com.uber.mylib; import org.jspecify.annotations.Nullable; /** * A sample class. */ public class ShortSet { static void log(Object x) { System.out.println(x.toString()); } static void foo() { log(null); } }
Java版本
$ java --version openjdk 21.0.4 2024-07-16 OpenJDK Runtime Environment (build 21.0.4+7-Ubuntu-1ubuntu222.04) OpenJDK 64-Bit Server VM (build 21.0.4+7-Ubuntu-1ubuntu222.04, mixed mode, sharing)
原因分析
- 依赖版本不兼容:使用的NullAway 0.10.15与Eisop Dataflow 3.39.0-eisop1版本不匹配,NullAway无法找到所需的Dataflow框架类
org.checkerframework.nullaway.dataflow.cfg.node.NodeVisitor。 - Java版本过高:NullAway 0.10.15对Java 21的支持不完善,旧版本未适配Java 21的类加载和编译器API变化,加剧了初始化失败问题。
解决方案
1. 升级到兼容的依赖版本
使用支持Java 21的NullAway新版本,搭配对应的Error Prone和Eisop Dataflow版本,修改脚本中的版本变量:
EP_VERSION=2.26.0 DATAFLOW_VERSION=3.42.0-eisop1 NULLAWAY_VERSION=0.10.20 JSPECIFY_VERSION=1.0.0
2. 重新下载依赖jar包
删除旧的jar文件,运行脚本重新下载匹配版本的依赖。
3. 执行编译检测
运行更新后的脚本,NullAway将成功初始化并检测到代码中的NPE问题,预期输出:
error: [NullAway] passing @Nullable expression where @NonNull is required log(null); ^ (see http://errorprone.info/bugpattern/NullAway)
内容的提问来源于stack exchange,提问作者Ziao Li
相关产品推荐
相关产品推荐

