Reputation: 34373
I've created a minimal application around Java's HttpsServer
.
I've installed an HttpHandler
that replies to a request with a short text message:
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);
}
};
When connecting to the server with curl, the server responds but the Java process keeps using an entire core, thus rendering the server unresponsive.
It's this line that triggers the issue:
responseBodyStream.close();
If we remove the line, the server keeps on working.
From the docs:
In order to correctly terminate each exchange, the output stream must be closed, even if no response body is being sent.
I've created a project to reproduce the issue.
Some potential clues I've found up till now:
SSLEngineImpl#writeRecord
in the thread HTTP-Dispatcher
allocates a lot of objectsI'm on Arch Linux 5.1.7 using OpenJDK 12.0.1+12. The version of curl is 7.65.1.
Is this a bug in the JDK? Or am I using HttpsServer
the wrong way?
Upvotes: 6
Views: 2860
Reputation: 98505
I could also reproduce the problem.
There is an infinite loop in SSLStreams.doClosure
- this is definitely a JDK bug.
HttpsServer worked fine in JDK 10, but starts looping in JDK 11. I guess the problem is that HttpsServer implementation has not been adapted to TLS v1.3 half-close policy appeared in JDK 11.
Fortunately, there is a workaround. Add -Djdk.tls.acknowledgeCloseNotify=true
JVM option. With this option HttpsServer will work as expected. See JDK-8208526 for details.
Upvotes: 7