У меня есть проект на основе Gradle, в котором выполняются тесты CI с использованием Github Action. Один из модулей основан на собственной библиотеке и загружает его как System.loadLibrary(LIBNAME)
.
Все работает нормально на машине разработчика, но, к сожалению, всегда дает сбой на CI с:
java.lang.ExceptionInInitializerError
at java.base/java.lang.Class.forName(Class.java:398)
at io.emeraldpay.polkaj.tx.TestKeys.<clinit>(TestKeys.groovy:24)
...
Caused by:
java.lang.NullPointerException
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2646)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:830)
at java.base/java.lang.System.loadLibrary(System.java:1873)
at io.emeraldpay.polkaj.schnorrkel.Schnorrkel.<clinit>(Schnorrkel.java:303)
... 7 more
ClassLoader.java:2646
- это просто:
2646: for (String sys_path : sys_paths) {
Это возможно, потому что в моем классе (здесь Schnorrkel
) я заставляю ClassLoader повторно инициализировать значения usr_paths
и sys_path
после добавления к ним собственной библиотеки. пути. Я делаю это в блоке класса static
, который должен запускаться только один раз.
Похоже, что существует гонка между разными static
инициализаторами, что возможно при наличии нескольких загрузчиков классов ( также я использую Groovy для тестов, так что очень вероятно). Итак, я предполагаю, что во время инициализации этих параллелей он стирает значение ClassLoader в одном потоке, но доступ из другого. Но я не уверен, как это проверить или убедиться, что этого не происходит.
Запуск Gradle с --no-parallel
не помогает. И я не могу воспроизвести ошибку на локальном компьютере.
Что может быть причиной и как это исправить?