Запустите анализатор NullAway, но столкнитесь с ошибкой утверждения при инициализации NullAway.

Вопрос или проблема

Я пытаюсь обнаружить исключения нулевых указателей в Java-файле с использованием NullAway. Однако NullAway не может быть запущен из-за ошибки утверждения, связанной с его инициализацией:

java.lang.AssertionError: com.google.errorprone.scanner.ErrorProneInjector$ProvisionException: Не удалось инициализировать 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)
Причина: com.google.errorprone.scanner.ErrorProneInjector$ProvisionException: Не удалось инициализировать 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
Причина: 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
Причина: 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
Причина: 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

Ниже приведен скрипт, который я использовал для выполнения NullAway. Я следовал инструкциям из Error Prone и внес некоторые изменения в соответствии с документацией NullAway:

EP_VERSION=2.23.0
DATAFLOW_VERSION=3.39.0-eisop1
NULLAWAY_VERSION=0.10.15
JSPECIFY_VERSION=1.0.0

# проверьте, загружены ли файлы, если нет, загрузите
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 файлы загружены"

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 "Компиляция завершена"

Исходный код “com/uber/mylib/ShortSet.java” идентичен примеру, предоставленному NullAway:

package com.uber.mylib;

import org.jspecify.annotations.Nullable;

/**
 * Пример класса.
 */
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 не может инициализироваться успешно. Спасибо за вашу помощь!

NullAway может быть успешно запущен и обнаружить NPE в коде.

Вам нужно добавить

<dependency>
    <groupId>org.checkerframework</groupId>
    <artifactId>dataflow-nullaway</artifactId>
</dependency>

в ваш classpath или processorpath (я не уверен, в какой из них).

Ответ или решение

Решение проблемы с инициализацией анализатора NullAway в Java

Проблема, с которой вы столкнулись, заключается в том, что анализатор NullAway не может быть инициализирован, из-за ошибки, связанной с отсутствующими классами, в частности, с классом org.checkerframework.nullaway.dataflow.cfg.node.NodeVisitor. Это ошибка возникает, когда необходимые зависимости отсутствуют в вашем класспасе или путь компилятора неверный.

Анализ ошибки

Ваше сообщение об ошибке указывает на следующие моменты:

  • AssertionError: Программа не была в состоянии завершить инициализацию NullAway из-за ошибки внедрения зависимостей.
  • NoClassDefFoundError: Отсутствие класса NodeVisitor.
  • ClassNotFoundException: Янбеен класс не найден в класспасе.

Эти ошибки подразумевают, что для корректной работы NullAway необходимы дополнительные зависимости, которые не были включены в проект.

Возможное решение

  1. Добавление зависимости:
    Чтобы решить проблему, необходимо добавить зависимость к dataflow-nullaway в ваш проект. Это можно сделать через систему сборки, такую как Maven или Gradle.

    Для Maven добавьте следующий код в файл pom.xml вашего проекта:

    <dependency>
       <groupId>org.checkerframework</groupId>
       <artifactId>dataflow-nullaway</artifactId>
       <version>3.39.0-eisop1</version> <!-- или соответствующая версия -->
    </dependency>

    Если вы используете Gradle, добавьте строку в секцию dependencies вашего файла build.gradle:

    implementation 'org.checkerframework:dataflow-nullaway:3.39.0-eisop1' // замените на актуальную версию
  2. Проверка вашего classpath и processorpath:
    Убедитесь, что в вашем скрипте, который вы используете для компиляции, dataflow-nullaway добавлен в classpath или processorpath. Например, передайте нужные зависимости в ваши флаги компилятора, как это сделано для других jar-файлов.

    Например:

    -processorpath $dataflow_errorprone_jar:$nullaway_jar:$dataflow_nullaway_jar
  3. Проверка версии Java:
    Обратите внимание, что вы используете OpenJDK 21. Убедитесь, что все зависимости, включая NullAway и его вспомогательные библиотеки, совместимы с этой версией Java. В некотором смысле, Java версии могут вводить дополнительные сложности при загрузке классов, поэтому стоит убедиться, что все используемые библиотеки поддерживают вашу версию JDK.

  4. Обновление или переустановка зависимостей:
    Если указанные выше шаги не помогли, попробуйте удалить, а затем снова установить зависимости вашего проекта. Возможно, некоторые jar-файлы повреждены или были загружены неправильно.

Заключение

Если после выполнения всех шагов ошибка не устранена, рекомендуется обратиться к официальной документации NullAway для получения дополнительных указаний. Возможно, нужно будет проверить совместимость версий используемых библиотек или связаться с сообществом разработчиков, чтобы получить более специфическую помощь.

Следуя данным рекомендациям, вы должны успешно инициализировать NullAway и использовать его для выявления исключений, связанных с null в вашем коде.

Оцените материал
Добавить комментарий

Капча загружается...