ADDITIONAL SYSTEM INFORMATION :
- Oracle JDK
java version "12.0.2" 2019-07-16
Java(TM) SE Runtime Environment (build 12.0.2+10)
Java HotSpot(TM) 64-Bit Server VM (build 12.0.2+10, mixed mode, sharing)
- Linux 64-bit
A DESCRIPTION OF THE PROBLEM :
When the connection times out, Socket.connect() sometimes throws SocketTimeoutException (for low timeouts set and triggered at the JVM level) but other times ConnectException (for timeouts by the kernel).
When the timeout is set to a low value (e.g., 3 seconds), it throws SocketTimeoutException with the message "connect timed out". But when the timeout is not set or set a high value and the connection times out at the network level (on my machine, it is set to 15 seconds), it throws ConnectException with the message "Connection timed out (Connection timed out)".
Note:
- In both cases, the exception messages clearly indicates it is the connection timeout.
- ConnectException does not extend SocketTimeoutException or vice versa
In both cases, it show throw SocketTimeoutException consistently.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Set connect timeout to a value that is greater than the timeout configured at the kernel level. See the executable test code below to reproduce.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect (Native Method)
at java.net.AbstractPlainSocketImpl.doConnect (AbstractPlainSocketImpl.java:399)
at java.net.AbstractPlainSocketImpl.connectToAddress (AbstractPlainSocketImpl.java:242)
at java.net.AbstractPlainSocketImpl.connect (AbstractPlainSocketImpl.java:224)
at java.net.SocksSocketImpl.connect (SocksSocketImpl.java:403)
at java.net.Socket.connect (Socket.java:591)
at com.example.ApacheHttpClient2.main (ApacheHttpClient2.java:17)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:567)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282)
at java.lang.Thread.run (Thread.java:835)
ACTUAL -
java.net.ConnectException: Connection timed out (Connection timed out)
at java.net.PlainSocketImpl.socketConnect (Native Method)
at java.net.AbstractPlainSocketImpl.doConnect (AbstractPlainSocketImpl.java:399)
at java.net.AbstractPlainSocketImpl.connectToAddress (AbstractPlainSocketImpl.java:242)
at java.net.AbstractPlainSocketImpl.connect (AbstractPlainSocketImpl.java:224)
at java.net.SocksSocketImpl.connect (SocksSocketImpl.java:403)
at java.net.Socket.connect (Socket.java:591)
at com.example.ApacheHttpClient2.main (ApacheHttpClient2.java:17)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:567)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282)
at java.lang.Thread.run (Thread.java:835)
---------- BEGIN SOURCE ----------
long started = System.nanoTime();
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress("example.com", 81), 50000); /** 50 seconds */
} finally {
System.out.println("timed out after (sec): " + (System.nanoTime() - started) / 1000000000L);
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
User applications may catch ConnectException in addition to SocketTImeoutException and examine the exception message to determine if the connection failed due to connection timeout.
FREQUENCY : always