SpringBoot3+POI+Log4j GraalVM Native Image运行时错误求解决方案
问题:Spring Boot 3 + GraalVM Native Image 集成 Apache POI 运行时出现隐藏类定义不支持错误
问题详情
用GraalVM Native Image构建Spring Boot 3应用,引入带Log4j依赖的Apache POI后,构建能成功,但运行时抛出Defining hidden classes at runtime is not supported错误。同样的场景在Spring Boot 2.7.1 + Spring Native环境下正常运行,试过添加native-image参数--initialize-at-run-time=org.apache.logging.log4j.spi.Provider但没用,求可行的配置方案。
运行错误日志
. ____ _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.0.0) 2022-12-06T11:53:05.855+08:00 INFO 18532 --- [ restartedMain] com.example.dataserver.Application : Starting AOT-processed Application using Java 17.0.5 with PID 18532 (D:\work-ide\IDEA\data-server\target\data-server.exe started by westinyang in D:\work-ide\IDEA\data-server\target) 2022-12-06T11:53:05.855+08:00 INFO 18532 --- [ restartedMain] com.example.dataserver.Application : No active profile set, falling back to 1 default profile: "default" 2022-12-06T11:53:05.855+08:00 INFO 18532 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2022-12-06T11:53:05.855+08:00 INFO 18532 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2022-12-06T11:53:05.889+08:00 INFO 18532 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2022-12-06T11:53:05.889+08:00 INFO 18532 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-12-06T11:53:05.889+08:00 INFO 18532 --- [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.1] 2022-12-06T11:53:05.897+08:00 INFO 18532 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-12-06T11:53:05.897+08:00 INFO 18532 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 41 ms 2022-12-06T11:53:05.920+08:00 INFO 18532 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2022-12-06T11:53:05.921+08:00 INFO 18532 --- [ restartedMain] com.example.dataserver.Application : Started Application in 0.072 seconds (process running for 0.078) ERROR StatusLogger Unable to load services for service class org.apache.logging.log4j.spi.Provider java.lang.InternalError: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defining hidden classes at runtime is not supported. at java.base@17.0.5/java.lang.invoke.InnerClassLambdaMetafactory.generateInnerClass(InnerClassLambdaMetafactory.java:413) at java.base@17.0.5/java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:315) at java.base@17.0.5/java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:228) at java.base@17.0.5/java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:341) at org.apache.logging.log4j.util.ServiceLoaderUtil.loadClassloaderServices(ServiceLoaderUtil.java:93) at org.apache.logging.log4j.util.ServiceLoaderUtil.loadServices(ServiceLoaderUtil.java:74) at org.apache.logging.log4j.util.ServiceLoaderUtil.loadServices(ServiceLoaderUtil.java:68) at org.apache.logging.log4j.util.ProviderUtil.<init>(ProviderUtil.java:67) at org.apache.logging.log4j.util.ProviderUtil.lazyInit(ProviderUtil.java:145) at org.apache.logging.log4j.util.ProviderUtil.hasProviders(ProviderUtil.java:129) at org.apache.logging.log4j.LogManager.<clinit>(LogManager.java:90) at org.apache.poi.util.IOUtils.<clinit>(IOUtils.java:43) at org.apache.poi.poifs.filesystem.FileMagic.valueOf(FileMagic.java:177) at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:309) at cn.hutool.poi.excel.WorkbookUtil.createBook(WorkbookUtil.java:120) at cn.hutool.poi.excel.WorkbookUtil.createBook(WorkbookUtil.java:70) at cn.hutool.poi.excel.ExcelReader.<init>(ExcelReader.java:71) at cn.hutool.poi.excel.ExcelReader.<init>(ExcelReader.java:50) at cn.hutool.poi.excel.ExcelUtil.getReader(ExcelUtil.java:151) at cn.hutool.poi.excel.ExcelUtil.getReader(ExcelUtil.java:127) at com.example.dataserver.AppRunner.run(AppRunner.java:23) at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:758) at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:748) at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) at com.example.dataserver.Application.main(Application.java:13) at java.base@17.0.5/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) at org.graalvm.nativeimage.builder/com.oracle.svm.core.windows.WindowsPlatformThreads.osThreadStartRoutine(WindowsPlatformThreads.java:178) Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defining hidden classes at runtime is not supported. at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) at java.base@17.0.5/java.lang.ClassLoader.defineClass0(ClassLoader.java:338) at java.base@17.0.5/java.lang.System$2.defineClass(System.java:2307) at java.base@17.0.5/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2439) at java.base@17.0.5/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClassAsLookup(MethodHandles.java:2420) at java.base@17.0.5/java.lang.invoke.MethodHandles$Lookup.defineHiddenClass(MethodHandles.java:2127) at java.base@17.0.5/java.lang.invoke.InnerClassLambdaMetafactory.generateInnerClass(InnerClassLambdaMetafactory.java:407) ... 28 more ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console... 2022-12-06T11:53:05.981+08:00 INFO 18532 --- [ restartedMain] com.example.dataserver.AppRunner : 3 2022-12-06T11:53:05.981+08:00 INFO 18532 --- [ restartedMain] com.example.dataserver.AppRunner : Service running on 127.0.0.1:8080
项目依赖配置(pom.xml)
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.10</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency>
已尝试的Native Image配置
<plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> <configuration> <buildArgs> <arg>--no-fallback</arg> <arg>--initialize-at-run-time=org.apache.logging.log4j.spi.Provider</arg> <arg>-H:+AddAllCharsets</arg> </buildArgs> </configuration> </plugin>
可行解决方案
方案1:调整初始化时机并添加反射配置
修改native-maven-plugin的buildArgs,替换原有的初始化参数,新增以下配置:
<plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> <configuration> <buildArgs> <arg>--no-fallback</arg> <arg>--initialize-at-run-time=org.apache.logging.log4j.util.ProviderUtil,org.apache.logging.log4j.util.ServiceLoaderUtil</arg> <arg>-H:+AddAllCharsets</arg> <arg>--enable-all-security-services</arg> </buildArgs> </configuration> </plugin>
同时在项目src/main/resources/META-INF/native-image目录下创建reflect-config.json文件(无对应目录则新建),内容如下:
[ { "name": "org.apache.logging.log4j.core.config.ConfigurationFactory", "allDeclaredConstructors": true }, { "name": "org.apache.logging.log4j.spi.Provider", "allDeclaredConstructors": true }, { "name": "org.apache.logging.log4j.util.ServiceLoaderUtil", "allDeclaredMethods": true } ]
方案2:排除POI中的Log4j依赖,改用Spring默认日志
如果不需要Log4j,可以直接排除POI的Log4j依赖,使用Spring Boot默认的Logback日志框架,修改pom.xml:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> <exclusions> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> </exclusion> </exclusions> </dependency>
方案3:升级GraalVM版本
尝试将GraalVM升级到22.3.0及以上版本,新版本对Java 17的隐藏类支持做了优化,可能直接解决该问题。
内容的提问来源于stack exchange,提问作者westinyang
相关产品推荐
相关产品推荐

