Среда:
- Версия GraalVM:< /strong> 21.0.5 (GraalVM 21.0.5 для Java 21)
- Версия Java: Java 21
- < strong>Версия Spring Boot: 3.3.5
- Версия EclipseStore: 2.0.0 (добавление этого вызывает проблему)
- Операционная система: Sonoma 14.6.1
Когда я добавляю EclipseStore в свое приложение Spring Boot и пытаюсь создать собственный образ с помощью GraalVM, я сталкиваюсь со следующей ошибкой, связанной с java.util.Collections$SetFromMap >:
Код: Выделить всё
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field final java.util.Map java.util.Collections$SetFromMap.m accessible: module java.base does not "opens java.util" to unnamed module @60a7e509
at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:177)
at org.eclipse.serializer.reflect.XReflect.setAccessible(XReflect.java:110)
...
Что я сделал Пробовал:
- Добавление --add-opens во время сборки:
В моем pom.xml я включил следующие аргументы сборки:Код: Выделить всё
--add-opens=java.base/java.util=ALL-UNNAMED
- Добавление --add-opens во время выполнения:
Обновлены аргументы сборки, чтобы передать параметр --add-opens в среду выполнения:Код: Выделить всё
-H:AdditionalRuntimeOptions=--add-opens=java.base/java.util=ALL-UNNAMED
- Регистрация подсказок по отражению:
В моем RuntimeHints.java< /code>, я зарегистрировал внутренний класс:Код: Выделить всё
hints.reflection().registerType( TypeReference.of("java.util.Collections$SetFromMap"), builder -> builder.withMembers(MemberCategory.values()) );
- Использование файла конфигурации отражения:
Создан рефлекс-конфигурация .json с необходимой конфигурацией.
Дополнительная информация:
- Репозиторий GitHub: LiveNathan/ nativeImageTest
- Связанное обсуждение: Обсуждение Eclipse Store на GitHub № 297
- Есть ли способ правильно настроить GraalVM и систему модулей Java, чтобы разрешить рефлексивный доступ к java.util.Collections$SetFromMap?
- Может ли эта проблема быть связана с несовместимостью EclipseStore и Java 21 или GraalVM 21.0.5?
- Существуют ли альтернативные подходы к устранению этой ошибки, не полагаясь на внутренние классы JDK?
Соответствующий код:
Главное изменение — добавление EclipseStore. Если я загружу новый проект из Spring Initializer и добавлю свой контроллер, он сможет скомпилироваться в собственный образ и запуститься. Как только я добавляю EclipseStore, ошибка возникает при запуске собственного образа. Кажется, ничто из того, что я пробовал выше, не изменило результат.
Код: Выделить всё
public class EclipseAccountAdapter {
private final EmbeddedStorageManager storageManager;
private static final Logger log = LoggerFactory.getLogger(EclipseAccountAdapter.class);
private final ApplicationContext context;
public EclipseAccountAdapter(EmbeddedStorageManager storageManager, ApplicationContext context) {
this.storageManager = storageManager;
this.context = context;
initializeRoot();
}
private void initializeRoot() {
if (storageManager.root() == null) {
log.info("Initializing root.");
storageManager.setRoot(new DataRoot());
storageManager.storeRoot();
}
}
@Write
public int save(Account account, StorerType storerType) {
getRoot().accounts().add(account);
store(getRoot().accounts().usernameToAccount(), storerType);
return getRoot().accounts().all().size();
}
@Read
public List findAll() {
return new ArrayList(getRoot().accounts().all());
}
private DataRoot getRoot() {
return (DataRoot) storageManager.root();
}
private void store(final Object object, StorerType storerType) {
try {
switch (storerType) {
case LAZY: {
Storer lazyStorer = storageManager.createLazyStorer();
lazyStorer.store(object);
lazyStorer.commit();
break;
}
case EAGER: {
Storer eagerStorer = storageManager.createEagerStorer();
eagerStorer.store(object);
eagerStorer.commit();
}
default:
storageManager.store(object);
}
} catch (final Throwable t) {
onStorageFailure(t);
}
}
private void onStorageFailure(final Throwable t) {
if (storageManager != null && storageManager.isRunning()) {
try {
log.error("Storage error! Shutting down storage...", t);
SpringApplication.exit(context, () -> 0);
} catch (final Throwable throwable) {
log.error(throwable.getMessage(), throwable);
}
}
DataRoot root = getRoot();
if (root != null) {
root.clear();
}
}
}
Вот частичный файл pom.xml, содержащий только ключевые зависимости и аргументы сборки GraalVM :
Код: Выделить всё
org.springframework.boot
spring-boot-starter
org.eclipse.store
storage-embedded
2.0.0
org.graalvm.buildtools
native-maven-plugin
После компиляции собственного образа с помощью ./mvnw -Pnative -DbuildArgs="-Ob" Native:compile -DskipTests и затем запускаем его:
Код: Выделить всё
2024-10-27T08:01:30.632-05:00 INFO 19610 --- [nativeImageTest] [ main] d.n.nativeImageTest.ServiceConfig : Initializing EmbeddedStorageManager...
2024-10-27T08:01:30.634-05:00 WARN 19610 --- [nativeImageTest] [ main] w.s.c.ServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accountController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'eclipseAccountAdapter': Unsatisfied dependency expressed through method 'eclipseAccountAdapter' parameter 0: Error creating bean with name 'injectStorageTest': Instantiation of supplied bean failed
2024-10-27T08:01:30.634-05:00 INFO 19610 --- [nativeImageTest] [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accountController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'eclipseAccountAdapter': Unsatisfied dependency expressed through method 'eclipseAccountAdapter' parameter 0: Error creating bean with name 'injectStorageTest': Instantiation of supplied bean failed
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'eclipseAccountAdapter': Unsatisfied dependency expressed through method 'eclipseAccountAdapter' parameter 0: Error creating bean with name 'injectStorageTest': Instantiation of supplied bean failed
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'injectStorageTest': Instantiation of supplied bean failed
Caused by: org.eclipse.serializer.exceptions.NoSuchNestedClassRuntimeException: No nested class java.util.Collections$SetFromMap found in class java.util.Collections
at org.eclipse.serializer.reflect.XReflect.getDeclaredNestedClass(XReflect.java:416)
at org.eclipse.serializer.persistence.binary.java.util.BinaryHandlerSetFromMap.New(BinaryHandlerSetFromMap.java:39)
Подробнее здесь: https://stackoverflow.com/questions/791 ... -java-util