我已经围绕Java的HttpsServer
创建了一个最小的应用程序。
我已经安装了HttpHandler
,该请求通过短信回复了请求:
return exchange -> {
try {
OutputStream responseBodyStream = exchange.getResponseBody();
byte[] response = "Trouble with HTTPS and curl\n"
.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, response.length);
responseBodyStream.write(response);
responseBodyStream.close();
// Note that exchange.close() also closes the exchange's input stream
// and output stream
} catch (Exception e) {
log.warn("Could not handle request", e);
}
};
使用curl连接到服务器时,服务器会做出响应,但是Java进程会继续使用整个内核,从而使服务器无响应。
以下是触发问题的行:
responseBodyStream.close();
如果我们删除该行,则服务器将继续工作。
来自docs:
为了正确终止每个交换,即使没有发送响应主体,也必须关闭输出流。
我已经创建了a project to reproduce个问题。
到目前为止,我已经发现了一些潜在线索:
SSLEngineImpl#writeRecord
中的HTTP-Dispatcher
分配了很多对象我在使用OpenJDK 12.0.1 + 12的Arch Linux 5.1.7上。 curl的版本是7.65.1。
这是JDK中的错误吗?还是我以错误的方式使用HttpsServer
?
答案 0 :(得分:3)
我也可以重现问题。
SSLStreams.doClosure
中存在一个无限循环-这绝对是一个JDK错误。
HttpsServer在JDK 10中工作正常,但在JDK 11中开始循环。我想问题是HttpsServer实现尚未适应JDK 11中出现的TLS v1.3半关闭策略。
幸运的是,有一种解决方法。添加-Djdk.tls.acknowledgeCloseNotify=true
JVM选项。使用此选项,HttpsServer将按预期工作。有关详细信息,请参见JDK-8208526。