检查AmazonS3空对象时getAmazonS3()类型报错修复
问题背景
需要实现AmazonS3实例空值检查逻辑,相关代码定义如下:
@Component public class AwsS3Client { private AmazonS3 amazonS3; public AmazonS3 getAmazonS3() { return this.amazonS3; } }
业务侧调用代码:
@Autowired private AwsS3Client awsS3Client; if (Objects.isNull(awsS3Client.getAmazonS3())) { awsS3Client.createSessionWithAssumeRoleCredentials(); }
执行awsS3Client.getAmazonS3()时抛出类型不匹配错误:
Required type: Object Provided: AmazonS3
当前环境信息:
- 使用AWS SDK版本为1.11.971
AmazonS3类定义在独立的第三方工具jar包中
根因分析
该报错是典型的类加载器冲突/类版本不一致问题:JVM判定两个类相同的前提不仅是类全限定名一致,还要求加载这两个类的类加载器是同一个。当前业务代码中识别到的AmazonS3类,和AwsS3Client组件内部引用的AmazonS3类来自不同jar包、被不同类加载器加载,JVM会认为二者是完全无关的两个类型。Objects.isNull()是泛型方法,做参数类型推断时无法匹配两个不同的AmazonS3类型,就会抛出上述类型不匹配错误。
这类问题几乎都是依赖传递导致多版本AWS SDK共存,或者第三方工具包shade了SDK类但未做类路径重定位引发的。
修复方案
按优先级从高到低选择方案:
- 统一全局AWS SDK版本
执行依赖分析命令排查所有引入的AWS SDK相关包(核心是aws-java-sdk-core、aws-java-sdk-s3两个包),排除重复引入的其他版本,保证所有模块、所有依赖传递引入的AWS SDK版本统一为1.11.971,从根源解决类冲突。- Maven环境执行命令:
mvn dependency:tree | grep aws-java-sdk - Gradle环境执行命令:
gradle dependencies | grep aws-java-sdk
- Maven环境执行命令:
- 空判断逻辑下沉到组件内部
如果第三方工具包已经将AWS SDK shade进包内、无法修改其依赖配置,就不要跨jar包直接操作AmazonS3类型实例,在AwsS3Client类内部新增空判断方法,避免跨类加载器的类型传递:
业务侧直接调用该方法判断即可:// 在AwsS3Client类中新增方法 public boolean isS3ClientNull() { return this.amazonS3 == null; }if (awsS3Client.isS3ClientNull()) { awsS3Client.createSessionWithAssumeRoleCredentials(); } - 临时规避方案
若需要快速验证逻辑,可绕开泛型类型检查,直接做原生null判断,手动将返回值向上转型为Object规避类型校验:
注意该方案仅能绕过当前的null判断报错,后续如果需要对返回的if ((Object)awsS3Client.getAmazonS3() == null) { awsS3Client.createSessionWithAssumeRoleCredentials(); }AmazonS3实例做方法调用、类型转换,依然会抛出类转换异常,必须优先解决根源的依赖冲突问题。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

