1. 从一次真实的线上故障说起:SSL 握手失败的排查
某次线上监控报警,核心业务系统的定时任务异常,日志中刷满了 javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake。该任务负责从合作伙伴处同步数据,使用 HTTPS 接口。初步排查发现对方服务正常,但本地 JDK 版本为 1.8.0_181,与报错堆栈显示的 1.8.0_45 存在差异。
错误堆栈指向 sun.security.ssl.SSLSocketImpl.readRecord 和 performInitialHandshake 等底层方法,根因是一个 EOFException: SSL peer shut down incorrectly。这意味着在 SSL 握手过程中,连接被非正常关闭。此类错误常见于调用外部 HTTPS 接口时,描述笼统,可能涉及网络、服务端配置或本地环境。在 JDK 1.8 环境下,尤其是较新补丁版本,一个容易被忽略的'坑'藏在 JRE 的配置文件里。
2. 深入解剖 SSLHandshakeException:不只是连接关闭
看到 Remote host closed connection during handshake,第一直觉往往是网络不稳定或服务端问题。但在 JDK 1.8 语境下,需考虑更深层原因。SSL/TLS 握手涉及协议版本、加密套件、证书交换等环节,任一环节不匹配均可能导致失败。
首先,理解错误的本质。 堆栈中的 EOFException 是关键线索,发生在 InputRecord.read() 方法中,表示尝试读取握手数据时流已结束。造成这种'连接中断'的原因,在 JDK 1.8 中高度可疑的是 JCE(Java Cryptography Extension)强度限制策略。
引入关键概念:加密算法强度。 出于历史原因,Oracle JDK 默认安装了一套称为'受限(Limited)'的加密策略文件,对可用加密算法及密钥长度做了限制。例如,受限策略下可能无法使用 AES-256 等高強度加密算法。而现代服务器(尤其是海外或遵循高安全标准的服务),在 SSL/TLS 握手时,会优先协商使用高强度加密套件。
矛盾产生: 当 JDK 1.8 客户端(使用受限策略)去连接要求使用高强度加密算法(如 AES-256)的服务器时,双方在协商加密套件阶段产生分歧。服务器要求使用 AES-256,而客户端受限策略不支持,导致握手失败。

