okhttp与jdk版本不兼容分析

1、背景

最近在部署应用的时候,代码几乎没有太大改动。结果报了如下错误【clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on JDK 9+】:

于是紧急回滚,但错误依旧存在。在参考了博客后,发现可能原因是jdk环境发生了改变。于是迅速查看jdk版本,发现云平台运维近期将jdk版本由1.8.0_232升级到了1.8.0_252。但当时也有一批微服务用到了相同版本的okhttp,却没有报相应的错误。在升级okhttp版本暂时规避了这个问题后,最近也抽时间对此进行了研究。

2、排查调用过程

1. 代码中okhttp的trustHttps字段设置是true,代表信任所有的https连接。具体实现时:

2. OkHttpClient.class中关于sslSocketFactory方法如下:

3.  Platform.class中关于findPlatform方法如下:

4.  Jdk9Platform是Platform的子类。Jdk9Platform.class中buildIfSupported方法如下:

可以看出来,3.x版本的okhttp中通过jdk中SSLParameters.class中包含setApplicationProtocols方法、SSLSocket.class中包含getApplicationProtocol来确定是jdk1.9以上版本。但在jdk 1.8.0_251之后的版本中都包含这两个方法。4.3.0版本以下的okhttp都会对这个误判。返回Jdk9Platform对象,步骤3直接返回jdk9对象。而在步骤2调用其trustManager方法时,由于父类和子类都包含trustManager方法,返回对象是子类,故会调用子类的实现(多态)。子类实现如下:

因此抛出不支持的异常。

5. 在jdk1.8.0_251之前的版本中在步骤3 会直接通过new Platform()创建父类对象,之后就会调用父类中的trustManager方法:

这样就不会报错了。

3、 okhttp 4.3.0的改进

Okhttp 4.X版本采用kotlin语言进行了编写,整体思路和Java版本区别不大。我们首先来看看okhttp是如何改进这个bug的:

我们在来看看新版本是如何判断jdk9版本的:

采用了从系统读取Java的主版本号,判断是否大于9来实现的。

4、 重载方法

我们看到2.2节中sslSocketFactory方法标记了@deprecated注解,重载的方法为:

重载方法将信任管理设为了输入参数。而且给出了使用建议:

其实就是调用sslSocketFactory时候传入trustManager。(推荐此做法,无论okhttp、okhttp版本是什么,都不会报错)。

5、 总结

针对jdk 1.8.0_251、okhttp4.3.0以下版本不兼容问题,报如下错误【clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on JDK 9+】

解决办法1:升级okhttp4.3.0以上版本或降级至jdk1.8.0_251之前版本。

解决办法2:调用sslSocketFactory时候传入trustManager。(推荐此做法,无论okhttp、okhttp版本是什么,都不会报错)。

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值