问题描述
我收到以下异常:
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.355 PDT|SSLSocketImpl.java:479|duplex close of SSLSocket<br>
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:1569|close the underlying socket<br>
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:1588|close the SSL connection (initiative)<br>
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:727|close inbound of SSLSocket<br>
javax.net.ssl|WARNING|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:500|SSLSocket duplex close Failed (
"throwable" : {
java.net.socketException: Socket is closed
at java.base/java.net.socket.shutdownInput(Socket.java:1538)
at java.base/sun.security.ssl.BaseSSLSocketImpl.shutdownInput(BaseSSLSocketImpl.java:216)
at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:742)
at java.base/sun.security.ssl.SSLSocketImpl.bruteForceCloseInput(SSLSocketImpl.java:692)
at java.base/sun.security.ssl.SSLSocketImpl.duplexCloSEOutput(SSLSocketImpl.java:553)
at java.base/sun.security.ssl.SSLSocketImpl.close(SSLSocketImpl.java:485)
at java.base/sun.net.www.http.HttpClient.closeServer(HttpClient.java:1058)
at java.base/sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:183)
at java.base/java.lang.Thread.run(Thread.java:834)
at java.base/jdk.internal.misc.InnocuousThread.run(InnocuousThread.java:134)
}
我真的很困惑这个错误是从哪里出现的。
解决方法
正在寻找相同的东西,发现 https://bugs.openjdk.java.net/browse/JDK-8255148 表明此日志记录具有误导性。
,我在使用 openJDK11 及更高版本时遇到过这种行为,这似乎是由于 Java 11 中为支持 TLSv1.3 新实现了 SSL/TLS 通道。当它被称为同时支持 TLSv1.3 的服务器时,注意到错误,JVM 尝试使用此协议打开一个通道,但没有运气,显然它尚未完全支持。
我通过强制使用 TLSv1.2 找到了一种解决方法(在 OpenJDK11 中很有用),只需在应用程序启动时将以下选项添加到 JVM:-Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2
请注意,此解决方案并不总是有效,它还取决于您的 Java 代码和使用的库。
第二种方法是降级到 Jdk1.8,默认版本不支持 TLSv1.3,但并不总是可行。
如果您想更详细地研究 TLS 握手,请在启动时添加以下 JVM 参数:-Djavax.net.debug=ssl
(有关更多详细信息,请将其设置为 all
)
编辑
从 2021 年 2 月起,当存储库添加了对 TLSv1.3 (https://updates.jenkins.io) 的支持时,在“附加管理器”中的更新期间,我最初在 openJDK11 上的 Jenkins 中遇到了此错误。在调查该问题的过程中,我发现并尝试使用 jdk11 以下代码 from jenkins issue report:
public class DownloadWebpageExample {
public static void main(String[] args) {
try {
URL url = new URL("https://updates.jenkins.io/download/plugins/plugin-util-api/1.2.5/plugin-util-api.hpi");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
readStream(con.getInputStream());
// Give output for the command line
} catch (Exception e) {
e.printStackTrace();
}
}
private static void readStream(InputStream in)
{
char[] buf = new char[1024];
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in));) {
while (reader.read(buf,1024) != -1) { }
} catch (IOException e) {
e.printStackTrace();
}
}
}
通过使用 java -Djavax.net.debug=ssl DownloadWebpageExample
运行它会产生如上所示的错误:
javax.net.ssl|DEBUG|01|main|2021-06-11 12:40:59.499 CEST|SSLSocketImpl.java:636|close inbound of SSLSocket
javax.net.ssl|WARNING|01|main|2021-06-11 12:40:59.501 CEST|SSLSocketImpl.java:494|SSLSocket duplex close failed (
"throwable" : {
java.net.SocketException: Socket is closed
at java.base/java.net.Socket.shutdownInput(Socket.java:1521)
使用 java -Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2 -Djavax.net.debug=ssl DownloadWebpageExample
执行它并不能解决问题。
我用许多 jdk 版本尝试了这段代码,我发现 jdk8 和 openJDK9 不受此行为的影响,但它在 openJDK11- 16.
在 Jenkins 中,我注意到一种不同的行为,通过在 /etc/sysconfig/jenkins
文件中添加如下参数解决了 openJDK11 的问题。对我来说,这是确认它也依赖于源代码实现的错误:
JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2"