Конфигурация Logback Groovy и GraalVM

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

Обычно при запуске и компиляции все в порядке, но когда я пытаюсь скомпилировать с Graal, я сталкиваюсь с некоторыми проблемами, которые я не могу понять, как решить.

Итак, из-за отсутствия какой-либо конкретной конфигурации, переданной в Грааль, я получаю следующую ошибку во время компиляции:

Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of net.logstash.logback.encoder.LogstashEncoder are allowed in the image heap as this class should be initialized at image runtime. Object has been initialized by the io.micr
onaut.runtime.Micronaut class initializer with a trace: 
        at net.logstash.logback.encoder.LogstashEncoder.<init>(LogstashEncoder.java:27)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:80)
        at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:74)
        at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1732)
        at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1556)

Я попробовал очень ленивый подход, разрешив инициализацию класса во время сборки, сделав следующее:

--initialize-at-build-time=net.logstash.logback.encoder.LogstashEncoder

Это привело только к тому, что эта опция требовалась для различных других классов, связанных с logstash, поэтому я пошел дальше и добавил следующее правило для всего пакета:

--initialize-at-build-time=net.logstash.logback

Это не решило проблему, но, в свою очередь, привело к следующей ошибке во время компиляции:

com.oracle.svm.core.util.UserError$UserException: Classes that should be initialized at run time got initialized during image building:
 ch.qos.logback.classic.gaffer.GafferConfigurator the class was requested to be initialized at build time (from the command line). ch.qos.logback.classic.gaffer.GafferConfigurator has been initialized without the native-image initialization instrumentation and the stack trace can't be tracked. Try avoiding to initialize the class that caused initialization of ch.qos.logback.classic.gaffer.GafferConfiguratorgroovy.lang.GroovySystem the class was requested to be initialized at build time (from the command line). io.micronaut.runtime.Micronaut caused initialization of this class with the following trace:
        at ch.qos.logback.classic.gaffer.GafferConfigurator.$getStaticMetaClass(GafferConfigurator.groovy)
        at ch.qos.logback.classic.gaffer.GafferConfigurator.<init>(GafferConfigurator.groovy)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at ch.qos.logback.classic.gaffer.GafferUtil.newGafferConfiguratorInstance(GafferUtil.java:52)
        at ch.qos.logback.classic.gaffer.GafferUtil.runGafferConfiguratorOn(GafferUtil.java:41)
        at ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:67)
        at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:150)
        at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
        at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
        at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
        at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
        at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
        at io.micronaut.runtime.Micronaut.<clinit>(Micronaut.java:46)

Я пробовал различные варианты правил, касающихся разрешения и запрещения инициализации при сборке или во время выполнения, но ни одно из них не помогло.

Итак, мой вопрос: как мне это преодолеть? Я пытаюсь определить класс, вызывающий инициализацию, но пока не могу.

Кому-нибудь удалось получить логбэк для работы с отличным файлом конфигурации и успешно скомпилировать в образ GraalVM?


person akortex91    schedule 10.10.2019    source источник


Ответы (1)


Из-за того, насколько динамичен Groovy, труднее ввести в действие собственный образ GraalVM (но не невозможно). Я рекомендую вам запустить приложение через агент трассировки и посмотреть, какая конфигурация отражения требуется, чтобы ваш logback.groovy файл стал работоспособным.

Скомпилируйте приложение в JAR и запустите приложение с:

java -agentlib:native-image-agent=config-output-dir=META-INF/native-image -jar build/myjar-all.jar

Затем посмотрите в сгенерированном reflect-config.json файле записи, относящиеся к logback, и включите их в свою конфигурацию.

В качестве альтернативы вы можете избежать хлопот, используя logback.xml

person Graeme Rocher    schedule 15.10.2019
comment
Большое спасибо за ответ. Если немного покопаться, это действительно может помочь в тех случаях, когда кто-то хочет создать собственный образ с элементами Groovy. Хотя моей проблемы там не было. На самом деле проблема возникла из-за зависимости кодировщика logstash, которую я не смог заставить нормально скомпилировать. То, что вы упомянули, действительно правильно, но это было еще одним препятствием в процессе, который я не смог решить. - person akortex91; 17.10.2019