Authorize.net Java SDK是否支持GraalVM Native Image构建
官方支持说明
截至当前,Authorize.net 未公开任何关于 anet-java-sdk 正式支持 GraalVM Native Image 架构的官方说明。
问题现象
项目迁移至 Native Image 架构构建原生镜像时,抛出如下两类不支持特性的错误:
Error: Unsupported features in 2 methods Detailed message: Error: Detected a MBean server in the image heap. This is currently not supported, but could be changed in the future. Management beans are registered in many global caches that would need to be cleared and properly re-built at image build time. Class of disallowed object: com.sun.jmx.mbeanserver.JmxMBeanServer To see how this object got instantiated use --trace-ob ject-instantiation=com.sun.jmx.mbeanserver.JmxMBeanServer. The object was probably created by a class initializer and is reachable from a static field. You can request class initializa tion at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point. Trace: Object was reached by indexing into array constant java.lang.Object[]@7504af74 reached by reading field java.util.ArrayList.elementData of constant java.util.ArrayList@24b75efc reached by scanning method javax.management.MBeanServerFactory.addMBeanServer(MBeanServerFactory.java:418) Call path from entry point to javax.management.MBeanServerFactory.addMBeanServer(MBeanServer): at javax.management.MBeanServerFactory.addMBeanServer(MBeanServerFactory.java:418) at javax.management.MBeanServerFactory.createMBeanServer(MBeanServerFactory.java:232) at javax.management.MBeanServerFactory.createMBeanServer(MBeanServerFactory.java:192) at com.oracle.svm.core.jdk.management.ManagementSupport.getPlatformMBeanServer(ManagementSupport.java:257) at com.oracle.svm.core.jdk.management.Target_java_lang_management_ManagementFactory.getPlatformMBeanServer(Target_java_lang_management_ManagementFactory.java:45) at org.apache.logging.log4j.core.jmx.Server.unregisterLoggerContext(Server.java:248) at org.apache.logging.log4j.core.LoggerContext.stop(LoggerContext.java:379) at org.apache.logging.log4j.core.LoggerContext$1.run(LoggerContext.java:320) at java.lang.Thread.run(Thread.java:829) at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:600) at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192) at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0) Error: type is not available in this platform: org.graalvm.compiler.hotspot.management.AggregatedMemoryPoolBean Trace: Object was reached by reading field java.lang.ref.Reference.referent of constant java.util.WeakHashMap$Entry@5e4acddb reached by indexing into array constant java.util.WeakHashMap$Entry[]@5eed71e9 reached by reading field java.util.WeakHashMap.table of constant com.sun.jmx.mbeanserver.MBeanIntrospector$MBeanInfoMap@33ac075d reached by scanning method com.sun.jmx.mbeanserver.MXBeanIntrospector.getMBeanInfoMap(MXBeanIntrospector.java:68) Call path from entry point to com.sun.jmx.mbeanserver.MXBeanIntrospector.getMBeanInfoMap(): at com.sun.jmx.mbeanserver.MXBeanIntrospector.getMBeanInfoMap(MXBeanIntrospector.java:68) at com.sun.jmx.mbeanserver.MBeanIntrospector.getClassMBeanInfo(MBeanIntrospector.java:416) at com.sun.jmx.mbeanserver.MBeanIntrospector.getMBeanInfo(MBeanIntrospector.java:392) at com.sun.jmx.mbeanserver.MBeanSupport.<init>(MBeanSupport.java:139) at com.sun.jmx.mbeanserver.MXBeanSupport.<init>(MXBeanSupport.java:66) at com.sun.jmx.mbeanserver.Introspector.makeDynamicMBean(Introspector.java:203) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:888) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:320) at com.sun.jmx.mbeanserver.JmxMBeanServer$2.run(JmxMBeanServer.java:1225) at com.oracle.svm.core.jdk.Target_java_security_AccessController.doPrivileged(SecuritySubstitutions.java:123) at java.util.ServiceLoader.loadProvider(ServiceLoader.java:859) at java.util.ServiceLoader$LayerLookupIterator.hasNext(ServiceLoader.java:952) at sun.java2d.SunGraphics2D.setRenderingHints(SunGraphics2D.java:1370) at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VARARGS_SunGraphics2D_setRenderingHints_8d5833c6be813de16ff61d40a14ac79dc4dda89c(generated:0)
异常栈未直接指向 Authorize.net SDK,但移除以下 Maven 依赖后构建问题完全消失,可确认该依赖是触发问题的根因:
<dependency> <groupId>net.authorize</groupId> <artifactId>anet-java-sdk</artifactId> <version>LATEST</version> </dependency>
此前尝试添加构建参数 --initialize-at-run-time=com.sun.jmx.mbeanserver.JmxMBeanServer 修复,未生效。
环境版本信息
- Java版本:"11.0.10" 2021-01-19 LTS
- Quarkus版本:2.5.0.Final
- GraalVM版本:21.3
- Maven版本:Apache Maven 3.8.1
根因分析与修复方案
anet-java-sdk 及其传递依赖未做 GraalVM AOT 构建适配,会在类初始化阶段触发 JMX MBeanServer 实例化,而 GraalVM 21.3 版本明确不允许构建期生成的 MBeanServer 实例存在于原生镜像堆中。
单独为 JmxMBeanServer 配置运行时初始化无效,是因为触发 MBean 注册逻辑的是 SDK 及其传递依赖的静态初始化块,而非 JmxMBeanServer 类本身,可按以下优先级尝试修复:
- 首先在 native-image 构建参数中添加
--initialize-at-run-time=net.authorize.**,将整个 Authorize SDK 的所有类配置为运行时初始化,绝大多数类初始化触发的构建问题可通过该配置解决 - 如果上述配置后仍报 JMX 相关错误,执行
mvn dependency:tree导出 SDK 的全量传递依赖列表,将依赖中涉及 log4j、JMX、javax.management 路径下触发初始化的类一并加入运行时初始化配置列表 - 如果以上配置均无法解决问题,建议放弃引入官方 Java SDK,直接通过 HTTP 客户端调用 Authorize.net 提供的 REST 接口实现业务逻辑,这是兼容性最稳定的方案
额外注意:Maven 依赖配置中不要使用LATEST作为版本号,固定具体的 SDK 发布版本可以避免版本自动更新带来的不可预期兼容问题。
内容的提问来源于stack exchange,提问作者fzj
相关产品推荐
相关产品推荐

