У меня возникла проблема: что я получаю NoClassDefFoundError, когда библиотека не находится в пути к классам во время выполнения.
Этого, конечно, можно было бы ожидать, если бы я выполнял код, ссылающийся на символы библиотеки. Но весь такой код никогда не выполняется (за флагом). Фактически, исключение возникает при первом доступе к классу, содержащему этот код.
Я уже немного ломаю голову над этим и думаю, что, возможно, мне не хватает некоторых сведений о семантика загрузки классов в JVM.
Я свел проблему к следующему:
Код: Выделить всё
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.StrictWarningsGuard;
public class Main {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
private static void thisMethodIsNotCalled() {
new CompilerOptions().addWarningsGuard(new StrictWarningsGuard());
}
}
Скомпилировать с помощью (jar, загруженного из maven):
Код: Выделить всё
javac -cp closure-compiler-v20240317.jar Main.java
Код: Выделить всё
$ java Main
Error: Unable to initialize main class Main
Caused by: java.lang.NoClassDefFoundError: com/google/javascript/jscomp/WarningsGuard
Почему это происходит? Я просматривал спецификацию JVM и не понимаю, как загрузка Main приведет к тому, что JVM попытается загрузить символы, указанные в thisMethodIsNotCalled.
Более любопытно, что замена содержимого thisMethodIsNotCalled на следующее не приводит к этой ошибке, поэтому, похоже, это вызвано очень специфическим взаимодействием.
Код: Выделить всё
new StrictWarningsGuard();
new CompilerOptions().addWarningsGuard(null);
Это происходит с OpenJDK 21 в Ubuntu 24.04:
Код: Выделить всё
$ java -version
openjdk version "21.0.3" 2024-04-16
OpenJDK Runtime Environment (build 21.0.3+9-Ubuntu-1ubuntu1)
OpenJDK 64-Bit Server VM (build 21.0.3+9-Ubuntu-1ubuntu1, mixed mode, sharing)
Подробнее здесь: https://stackoverflow.com/questions/785 ... sspath-but