You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3 Native Image运行时出现LDAPS通信异常问题

问题:Native Image运行Spring Boot 3.0.1时LDAPS通信失败

使用GraalVM Native Image运行Spring Boot 3.0.1项目时出现LDAPS通信失败,但基于JVM的uber jar运行正常。

环境信息

openjdk version "17.0.5" 2022-10-18
OpenJDK Runtime Environment GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08)
OpenJDK 64-Bit Server VM GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08, mixed mode, sharing)

堆栈跟踪

org.springframework.ldap.CommunicationException: xxx-ad-vip.xxx.com:636
    at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:108) ~[na:na]
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:363) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:147) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:166) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:367) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:319) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:626) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:596) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:1661) ~[ldap-service:3.0.0]
    at com.vmware.ldapservice.serviceImpl.LDAPServiceImpl.getADAttributes(LDAPServiceImpl.java:82) ~[ldap-service:na]
    at java.base@17.0.5/java.lang.reflect.Method.invoke(Method.java:568) ~[ldap-service:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[na:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[ldap-service:6.0.3]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[ldap-service:6.0.3]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752) ~[na:na]
    at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:54) ~[ldap-service:6.0.3]
    at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:366) ~[ldap-service:6.0.3]
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:421) ~[ldap-service:6.0.3]
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345) ~[ldap-service:6.0.3]
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64) ~[ldap-service:6.0.3]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[ldap-service:6.0.3]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752) ~[na:na]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) ~[na:na]
    at com.xxx.ldapservice.serviceImpl.LDAPServiceImpl$$SpringCGLIB$$0.getADAttributes(<generated>) ~[ldap-service:na]
    at com.xxx.ldapservice.controller.LdapController.lambda$0(LdapController.java:34) ~[ldap-service:na]
    at java.base@17.0.5/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ~[na:na]
    at java.base@17.0.5/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) ~[na:na]
    at java.base@17.0.5/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[ldap-service:na]
    at java.base@17.0.5/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[na:na]
    at java.base@17.0.5/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[ldap-service:na]
    at java.base@17.0.5/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[ldap-service:na]
    at java.base@17.0.5/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[ldap-service:na]
    at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) ~[ldap-service:na]
    at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:203) ~[na:na]
Caused by: javax.naming.CommunicationException: xxx-ad-vip.xxx.com:636
    at java.naming@17.0.5/com.sun.jndi.ldap.Connection.<init>(Connection.java:253) ~[na:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:137) ~[na:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1616) ~[na:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2848) ~[na:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:348) ~[na:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxFromUrl(LdapCtxFactory.java:225) ~[ldap-service:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:189) ~[ldap-service:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:243) ~[ldap-service:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154) ~[ldap-service:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84) ~[ldap-service:na]
    at java.naming@17.0.5/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:732) ~[ldap-service:na]
    at java.naming@17.0.5/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305) ~[ldap-service:na]
    at java.naming@17.0.5/javax.naming.InitialContext.init(InitialContext.java:236) ~[ldap-service:na]
    at java.naming@17.0.5/javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:154) ~[na:na]
    at org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:42) ~[ldap-service:3.0.0]
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:351) ~[ldap-service:3.0.0]
    ... 32 common frames omitted
Caused by: java.lang.NoSuchMethodException: javax.net.ssl.SSLSocketFactory.getDefault()
    at java.base@17.0.5/java.lang.Class.getMethod(DynamicHub.java:2227) ~[ldap-service:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.Connection.createSocket(Connection.java:293) ~[na:na]
    at java.naming@17.0.5/com.sun.jndi.ldap.Connection.<init>(Connection.java:232) ~[na:na]
    ... 47 common frames omitted

核心问题

项目运行时找不到javax.net.ssl.SSLSocketFactory.getDefault()方法,导致LDAPS通信失败。这是因为GraalVM Native Image在静态编译时未自动包含该反射调用的方法。

解决方案

方案1:使用Spring Boot AOT自动生成配置

Spring Boot 3支持AOT(提前编译)功能,可自动处理Native Image所需的反射、资源等配置:

  • Maven项目执行:
./mvnw spring-boot:process-aot
  • Gradle项目执行:
./gradlew processAot

执行完成后再构建Native Image,AOT会自动生成包含SSLSocketFactory.getDefault()方法的反射配置。

方案2:手动添加反射配置文件

在项目的src/main/resources/META-INF/native-image目录下创建reflect-config.json文件,内容如下:

[
  {
    "name": "javax.net.ssl.SSLSocketFactory",
    "methods": [
      {
        "name": "getDefault",
        "parameterTypes": []
      }
    ]
  }
]

构建Native Image时,GraalVM会读取该配置文件,将指定方法纳入编译范围。

方案3:构建Native Image时直接指定参数

在构建Native Image的命令中添加反射参数,强制包含该方法:

native-image --reflect-config=src/main/resources/META-INF/native-image/reflect-config.json -jar your-application.jar

或者直接指定初始化该类:

native-image --initialize-at-run-time=javax.net.ssl.SSLSocketFactory -jar your-application.jar

内容的提问来源于stack exchange,提问作者Ladu anand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:20:33