Spring Boot3+GraalVM Native Image启动时Mybatis LoggerFactory构造器缺失
问题:Spring Boot 3 + JDK19 + GraalVM构建Native Image时MyBatis日志构造器及段错误问题
环境配置
- Spring Boot 3
- JDK 19
- GraalVM ce-java19-22.3
初始错误:MyBatis LoggerFactory找不到构造器
生成Native Image后运行./target/demo_boot3,抛出java.lang.ExceptionInInitializerError,根源是MyBatis的LoggerFactory无法找到构造器。
尝试手动通过静态方法初始化LogFactory,代码如下:
try { LogFactory.useSlf4jLogging(); } catch (Exception e) { e.printStackTrace(); } try { LogFactory.useCommonsLogging(); } catch (Exception e) { e.printStackTrace(); } try { LogFactory.useLog4J2Logging(); } catch (Exception e) { e.printStackTrace(); } try { LogFactory.useJdkLogging(); } catch (Exception e) { e.printStackTrace(); } try { LogFactory.useNoLogging(); } catch (Exception e) { e.printStackTrace(); }
但仍报错:
org.apache.ibatis.logging.LogException: Error setting Log implementation. Cause: java.lang.NoSuchMethodException: org.apache.ibatis.logging.slf4j.Slf4jImpl.<init>(java.lang.String) at org.apache.ibatis.logging.LogFactory.setImplementation(LogFactory.java:113) at org.apache.ibatis.logging.LogFactory.useSlf4jLogging(LogFactory.java:63) at com.example.demo.boot3.DemoBoot3Application.<clinit>(DemoBoot3Application.java:14) Caused by: java.lang.NoSuchMethodException: org.apache.ibatis.logging.slf4j.Slf4jImpl.<init>(java.lang.String) at java.base@19.0.1/java.lang.Class.getConstructor0(DynamicHub.java:3641) at java.base@19.0.1/java.lang.Class.getConstructor(DynamicHub.java:2324) at org.apache.ibatis.logging.LogFactory.setImplementation(LogFactory.java:106) ... 2 more
而该构造器实际存在:
public Slf4jImpl(String clazz) { Logger logger = LoggerFactory.getLogger(clazz); if (logger instanceof LocationAwareLogger) { try { // check for slf4j >= 1.6 method signature logger.getClass().getMethod("log", Marker.class, String.class, int.class, String.class, Object[].class, Throwable.class); log = new Slf4jLocationAwareLoggerImpl((LocationAwareLogger) logger); return; } catch (SecurityException | NoSuchMethodException e) { // fail-back to Slf4jLoggerImpl } } // Logger is not LocationAwareLogger or slf4j version < 1.6 log = new Slf4jLoggerImpl(logger); }
使用GraalVM Agent生成元数据后的新问题
用GraalVM Agent生成Native Image元数据后,构造器错误消失,但出现类预定义失败:
Error: Failed to prepare class with hash cb87220bbf3b7662f36953383b7b9076fdf52ee5b3314b7d90ba1bf30ffdc924 from file:/Users/cook/work/pieland/java_demo/demo_boot3/target/classes/META-INF/native-image/agent-extracted-predefined-classes/ for predefinition
移除predefined-classes-config和org.springframework.boot.loader后,Native Image编译成功,但运行时出现段错误:
[ [ SubstrateSegfaultHandler caught a segfault in thread 0x00007fb603c0a3c0 ] ] siginfo: si_signo: 11, si_code: 0, si_addr: 0x0000000000000000 Current timestamp: 1670326122279 General purpose register values: RAX 0x0000000114aa4568 points into the image heap (read-only huge) RBX 0x0000000001311548 is an unknown value RCX 0xfffffffffffffff8 is an unknown value RDX 0x0000000000000003 is an unknown value RBP 0x0000000117bf3530 points into an aligned TLAB chunk of thread 0x00007fb603c0a3c0 is an object of type java.nio.HeapByteBuffer RSI 0x0d8e5211a2400d8e is an unknown value RDI 0x0d8e521090000d8e is an unknown value RSP 0x00007ffee30ce7b0 points into the stack for thread 0x00007fb603c0a3c0 R8 0x0000000112400000 is the heap base R9 0x0000000117bf38e8 points into an aligned TLAB chunk of thread 0x00007fb603c0a3c0 is an object of type java.util.LinkedHashMap R10 0x0000000117bf3518 points into an aligned TLAB chunk of thread 0x00007fb603c0a3c0 is an object of type jdk.internal.reflect.ConstantPool R11 0x000000011317ce30 points into the image heap (read-only references) is the hub of org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedJetty R12 0x0000000112400000 is the heap base R13 0x0000000113678198 points into the image heap (read-only relocatables) is the hub of org.springframework.core.annotation.AnnotationAttributes R14 0x0000000112400000 is the heap base R15 0x00007fb603c0a3c0 is a thread EFL 0x0000000000010206 is an unknown value RIP 0x000000010e08a586 points into AOT compiled code Printing Instructions (ip=0x000000010e08a586): 0x000000010e08a566: 0x5f 0x14 0xff 0x90 0x48 0x8b 0x3c 0x05 0x00 0x00 0x00 0x00 0x49 0x8d 0x34 0x3e 0x000000010e08a576: 0x48 0x85 0xff 0x0f 0x84 0x1e 0x00 0x00 0x00 0x48 0xc7 0xc1 0xf8 0xff 0xff 0xff 0x000000010e08a586: 0x49 0x23 0x0c 0x3e 0x48 0xbf 0x48 0x15 0x31 0x01 0x00 0x00 0x00 0x00 0x48 0x3b 0x000000010e08a596: 0xf9 0x0f 0x85 0x21 0x00 0x00 0x00 0x41 0x83 0x6f 0x10 0x01 0x0f 0x8e 0x08 0x00
最终验证与结论
移除MyBatis/JDBC后,应用运行正常。启动速度对比:
- GraalVM Native Image启动耗时:0.073秒
- Spring Boot Jar启动耗时:1.987秒
- 速度提升约90%
目前MyBatis或JDBC暂不支持GraalVM Native Image,AOT技术尚未成熟,使用时易遇到未知问题。
内容的提问来源于stack exchange,提问作者Pie Land
相关产品推荐
相关产品推荐

