When setting spring.jmx.enabled
to true
in a Spring Boot application and building a native image the native image fails with the following exception during startup:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mbeanExporter': Instantiation of supplied bean failed
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1220) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo:6.0.10]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo:6.0.10]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[demo:6.0.10]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:941) ~[demo:6.0.10]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[demo:6.0.10]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[demo:3.1.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436) ~[demo:3.1.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[demo:3.1.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[demo:3.1.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[demo:3.1.1]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[demo:na]
Caused by: java.lang.IllegalArgumentException: Only values of autodetect constants allowed
at org.springframework.jmx.export.MBeanExporter.setAutodetectMode(MBeanExporter.java:237) ~[demo:6.0.10]
at org.springframework.jmx.export.annotation.AnnotationMBeanExporter.<init>(AnnotationMBeanExporter.java:51) ~[demo:6.0.10]
at org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration.mbeanExporter(JmxAutoConfiguration.java:68) ~[demo:3.1.1]
at org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration__BeanDefinitions.lambda$getMbeanExporterInstanceSupplier$1(JmxAutoConfiguration__BeanDefinitions.java:40) ~[na:na]
at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:68) ~[demo:6.0.10]
at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:54) ~[demo:6.0.10]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$2(BeanInstanceSupplier.java:200) ~[na:na]
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58) ~[demo:6.0.10]
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46) ~[demo:6.0.10]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:212) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:200) ~[na:na]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:947) ~[demo:6.0.10]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214) ~[demo:6.0.10]
... 16 common frames omitted
This is due to missing reflection configuration on fields of MBeanExporter
, which is required by the new Constants(MBeanExporter.class)
call here: https://github.com/spring-projects/spring-framework/blob/main/spring-context/src/main/java/org/springframework/jmx/export/MBeanExporter.java#L142
After adding a reflection-configuration.json
with the following content to the application the error no longer occurs:
[
{
"name": "org.springframework.jmx.export.MBeanExporter",
"allDeclaredFields": true
}
]
Is it reasonable to add this reflection configuration to Spring?
Steps to reproduce
- Initialize a new Spring Boot app with Native Image support using Spring Initializr
- Set
spring.jmx.enabled: true
inapplication.properties
- Build native image using
mvn native:compile -Pnative
- Start the application and observe the exception
Comment From: sbrannen
Is it reasonable to add this reflection configuration to Spring?
If we wish to continue using Constants
for MBeanExporter
, then yes.
However, I think we should consider a different approach to Constants
that does not require reflection -- for example, using an enum
internally with a mapping from the existing constants to enum constants.
Comment From: sbrannen
However, I think we should consider a different approach to
Constants
that does not require reflection -- for example, using anenum
internally with a mapping from the existing constants to enum constants.
Since Constants
is an outdated mechanism that predates enum
support introduced in Java 5, we plan to revise the internals of MBeanExporter
to avoid the use of reflection via Constants
.
In light of that, I have changed the title of this issue.
Comment From: sbrannen
Update
- 6.0.11: This issue will address the need for reflection hints in a GraalVM native image.
- 6.1: #30851
Comment From: sbrannen
@beckermarc, the changes to MBeanExporter
will be available in upcoming 6.0.11 snapshots.
If you can verify that the changes work for you with 6.0.11 snapshots, we'd be grateful!
Otherwise, please give it a try once 6.0.11 has been released.
Thanks
Comment From: beckermarc
Thanks @sbrannen! 🚀 I was able to confirm that the reflection metadata is no longer required with a 6.0.11 snapshot
Comment From: sbrannen
I was able to confirm that the reflection metadata is no longer required with a 6.0.11 snapshot
Great!
Thanks so much for confirming this, @beckermarc. 👍