调用外部Jar触发DocDB连接时出现AwsCredentials类找不到异常求助
问题描述
我在建立DocDB Client连接时遇到了ClassNotFoundException,具体情况如下:
- 代码仅引用了
software.amazon.awssdk.auth.credentials.AwsCredentialsProvider类,未直接使用software.amazon.awssdk.auth.credentials.AwsCredentials,但运行时却抛出该类找不到的异常 - 直接调用a.jar中的测试连接逻辑能成功建立连接,但通过b.jar调用a.jar里的相同逻辑时触发异常
- 已确认a.jar和b.jar的依赖Jar列表完全一致
代码实现
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; AwsCredentialsProvider getAwsCredentialsProvider() throws Exception { AwsSecretsManagerConfig conf = null; try { conf = this.ds.getAwsSecretsManagerConfig(); } catch (Exception e) { throw new Exception("failed Connection"); } String accessId = ""; String secreteAccessKey = ""; try { accessId = conf.getDecryptedAccessId(); } catch (Exception e1) { throw new Exception("failed Connection"); } try { secreteAccessKey = conf.getDecryptedSecretAccessKey(); } catch (Exception e1) { throw new Exception("failed Connection"); } //get aws connection configuration AwsSecretManagerConnectionConfig connectConfig = new AwsSecretManagerConnectionConfig(accessId,secreteAccessKey,conf.getAuthType(),datasource.getRegionName(),conf.getRoleArn()); String awsVariables = "accessId: " + accessId + " ,secreteAccessKey: " + secreteAccessKey + " ,conf.getAuthType(): " + conf.getAuthType() + " ,datasource.getRegionName(): " + datasource.getRegionName() + " ,conf.getRoleArn(); " + conf.getRoleArn(); System.out.println("inside db class method getAwsCredentialsProvider awsVariables - " + awsVariables); return AWSAuthenticationUtil.buildAWSCredentialsProvider(connectConfig); }
异常堆栈
Exception stacktrace : Caused by: java.lang.ClassNotFoundException: software.amazon.awssdk.auth.credentials.AwsCredentials at java.net.URLClassLoader.findClass(URLClassLoader.java:610) ~[?:1.8.0] at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:948) ~[?:2.9 (09-08-2023)] at java.lang.ClassLoader.loadClass(ClassLoader.java:893) ~[?:2.9 (09-08-2023)] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:353) ~[?:1.8.0] at java.lang.ClassLoader.loadClass(ClassLoader.java:876) ~[?:2.9 (09-08-2023)] ... 11 more
排查思路与解决方案
- 检查间接依赖:你的代码没直接用
AwsCredentials,但AWSAuthenticationUtil.buildAWSCredentialsProvider()方法内部或者AwsCredentialsProvider的实现类可能依赖这个类。确认b.jar的类加载路径里,aws-sdk-auth相关的jar包是否存在,直接跑a.jar时该jar能被加载,但b.jar的运行环境可能因为类加载隔离找不到它。 - 排查类加载器隔离:如果b.jar运行在Tomcat、Spring Boot这类容器或模块化环境中,可能存在类加载器隔离问题。直接跑a.jar用的是系统类加载器,而b.jar被其他类加载器加载,导致无法访问
AwsCredentials所在的jar包。可以在异常前后加代码打印类加载器信息:System.out.println(AwsCredentialsProvider.class.getClassLoader());,如果能临时引入类的话再打印AwsCredentials.class.getClassLoader(),对比两者是否一致。 - 检查依赖版本冲突:哪怕依赖列表一致,也可能存在传递依赖导致的版本冲突。比如b.jar的其他依赖引入了低版本的aws-sdk,覆盖了a.jar需要的版本,而低版本里没有
AwsCredentials类。用mvn dependency:tree(Maven)或gradle dependencies(Gradle)查看实际依赖树,确认aws-sdk相关组件版本统一。 - 检查Jar打包问题:如果b.jar是fat jar,确认是否正确包含了所有依赖;如果用了shade打包,检查是否导致aws-sdk的类被重命名或丢失。对比a.jar和b.jar的内部结构,确认aws-sdk相关类是否存在。
- 排查运行环境差异:直接跑a.jar和通过b.jar调用的环境可能不同,比如JVM参数、环境变量。检查是否有
-Xbootclasspath、-Djava.class.path这类参数修改了类加载路径,导致依赖jar没被包含。
内容的提问来源于stack exchange,提问作者SRP
相关产品推荐
相关产品推荐

