Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8176646 | 10 | Pavel Rappo | P3 | Resolved | Fixed | b03 |
This can be reproduced with following WebSocket scenario. But I don't think it is only a WebSocket problem. It looks to be a problem in current java.net.http.*HttpConnection implementation
//A simple test to reproduce the problem
public class WSReconnectTest {
public static void main(String[] args) throws Exception {
String wsURL = "your_ws_endpoint";
connect(wsURL);
connect(wsURL);
}
/**
* Tests send and receive plain text messages with different length.
* @throws Exception
*/
static void connect(String url) throws Exception {
Listener l = new Listener() {
@Override public void onError(WebSocket webSocket, Throwable error) {
System.err.println(error);
error.printStackTrace();
}
};
URI uri = new URI(url);
WebSocket ws= WebSocket.newBuilder(uri, l).buildAsync().get();
ws.sendClose().get();
}
}
It will fail immediately at the second connect attempt. Please refer to the test output:----------System.err:(24/1946)----------
java.util.concurrent.ExecutionException: java.io.IOException: Connection closed
at java.util.concurrent.CompletableFuture.reportGet(java.base@9-internal/CompletableFuture.java:395)
at java.util.concurrent.CompletableFuture.get(java.base@9-internal/CompletableFuture.java:1999)
at WSReconnectTest.connect(WSReconnectTest.java:58)
at WSReconnectTest.main(WSReconnectTest.java:42)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-internal/Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-internal/NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-internal/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base@9-internal/Method.java:535)
at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:110)
at java.lang.Thread.run(java.base@9-internal/Thread.java:843)
Caused by: java.io.IOException: Connection closed
at java.net.http.Http1Response.readHeaders(java.httpclient@9-internal/Http1Response.java:72)
at java.net.http.Http1Exchange.lambda$getResponseAsyncImpl$0(java.httpclient@9-internal/Http1Exchange.java:190)
at java.net.http.Utils.lambda$singleThreadExecutor$5(java.httpclient@9-internal/Utils.java:495)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@9-internal/ThreadPoolExecutor.java:1158)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@9-internal/ThreadPoolExecutor.java:632)
at java.lang.Thread.run(java.base@9-internal/Thread.java:843)
at jdk.internal.misc.InnocuousThread.run(java.base@9-internal/InnocuousThread.java:122)
"java.io.IOException: Connection closed" is the cause of failing to reconnect.
According java.net.http.HttpConnection.getConnectionImpl(xxx), it will try to get pooled connection if exists. But the pooled connection never got removed during closing connection. So the next attempt to connect will get the same connection which has been closed.
//A simple test to reproduce the problem
public class WSReconnectTest {
public static void main(String[] args) throws Exception {
String wsURL = "your_ws_endpoint";
connect(wsURL);
connect(wsURL);
}
/**
* Tests send and receive plain text messages with different length.
* @throws Exception
*/
static void connect(String url) throws Exception {
Listener l = new Listener() {
@Override public void onError(WebSocket webSocket, Throwable error) {
System.err.println(error);
error.printStackTrace();
}
};
URI uri = new URI(url);
WebSocket ws= WebSocket.newBuilder(uri, l).buildAsync().get();
ws.sendClose().get();
}
}
It will fail immediately at the second connect attempt. Please refer to the test output:----------System.err:(24/1946)----------
java.util.concurrent.ExecutionException: java.io.IOException: Connection closed
at java.util.concurrent.CompletableFuture.reportGet(java.base@9-internal/CompletableFuture.java:395)
at java.util.concurrent.CompletableFuture.get(java.base@9-internal/CompletableFuture.java:1999)
at WSReconnectTest.connect(WSReconnectTest.java:58)
at WSReconnectTest.main(WSReconnectTest.java:42)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-internal/Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-internal/NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-internal/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base@9-internal/Method.java:535)
at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:110)
at java.lang.Thread.run(java.base@9-internal/Thread.java:843)
Caused by: java.io.IOException: Connection closed
at java.net.http.Http1Response.readHeaders(java.httpclient@9-internal/Http1Response.java:72)
at java.net.http.Http1Exchange.lambda$getResponseAsyncImpl$0(java.httpclient@9-internal/Http1Exchange.java:190)
at java.net.http.Utils.lambda$singleThreadExecutor$5(java.httpclient@9-internal/Utils.java:495)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@9-internal/ThreadPoolExecutor.java:1158)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@9-internal/ThreadPoolExecutor.java:632)
at java.lang.Thread.run(java.base@9-internal/Thread.java:843)
at jdk.internal.misc.InnocuousThread.run(java.base@9-internal/InnocuousThread.java:122)
"java.io.IOException: Connection closed" is the cause of failing to reconnect.
According java.net.http.HttpConnection.getConnectionImpl(xxx), it will try to get pooled connection if exists. But the pooled connection never got removed during closing connection. So the next attempt to connect will get the same connection which has been closed.
- backported by
-
JDK-8176646 Pooled HttpConnection should be removed during close
-
- Resolved
-