J2SE Version (please include all output from java -version flag):
java version "1.4.2-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-beta-b19)
Java HotSpot(TM) Client VM (build 1.4.2-beta-b19, mixed mode)
Does this problem occur on J2SE 1.3, 1.4 or 1.4.1? Yes / No (pick one)
Yes (tested with 1.4.1)
Operating System Configuration Information (be specific):
Windows 2000, but it should also happen on other platforms.
Hardware Configuration Information (be specific):
regular P4 PC
Bug Description:
RMI reuses RMI connections even if I set sun.rmi.transport.connectionTimeout property to "0".
Steps to Reproduce (be specific):
Code to reproduce this bug is not trivial, but bugfix should be. If I make two consecutive RMI calls, same RMI connection is used (not always, but quite often), even if I set sun.rmi.transport.connectionTimeout property to zero.
I need to set different timeouts for calls of different methods of the same remote object. As RMI lacks this functionality, I've made my own RMISocketFactory, that makes it possible - but connections should not be reused, to make it work.
Please see the attachment "rmitest.jar" for test case.
Steps to reproduce the problem:
1. Put rmitest.jar on the classpath.
2. Run rmitest.RmiServer
3. Run rmiTest.RmiClient
The result is:
Start
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
Got exception: java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketTimeoutException: Read timed out
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketTimeoutException: Read timed out
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:203)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:133)
at rmitest.RmiServer_Stub.rGetData(RmiServer_Stub.java:35)
at rmitest.RmiClient.main(RmiClient.java:16)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
at java.io.BufferedInputStream.read(BufferedInputStream.java:201)
at java.io.DataInputStream.readByte(DataInputStream.java:331)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:189)
... 3 more
, as the response from RmiServer takes 1000ms, but RmiClient reused the socket and therefore crashed.
If I uncomment the first sleep (the code in RmiClient looks like):
Thread.sleep(1);
TimeoutableRMISocketFactory.setTimeout(0, true);
rmiServer.rGetData("To je tudi en test.");
//Thread.sleep(1);
//TimeoutableRMISocketFactory.setTimeout(100, true);
rmiServer.rGetData("To je tudi en test.");
, this is what I get:
Start
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 0
Done.
Actually - this is also wrong, as the second RMI call should be performed with the default timeout (500ms), but socket from the first RMI call was resused.
If I ucomment also the second sleep, I get what this code really should do:
Start
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 0
--> Created socket with soTimeout: 500
Got exception: java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketTimeoutException: Read timed out
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketTimeoutException: Read timed out
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:203)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:133)
at rmitest.RmiServer_Stub.rGetData(RmiServer_Stub.java:35)
at rmitest.RmiClient.main(RmiClient.java:19)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
at java.io.BufferedInputStream.read(BufferedInputStream.java:201)
at java.io.DataInputStream.readByte(DataInputStream.java:331)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:189)
... 3 more
, and if I use the code like this:
Thread.sleep(1);
TimeoutableRMISocketFactory.setTimeout(0, true);
rmiServer.rGetData("To je tudi en test.");
Thread.sleep(1);
TimeoutableRMISocketFactory.setTimeout(100, true);
rmiServer.rGetData("To je tudi en test.");
the result is also what I expected:
Start
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 500
--> Created socket with soTimeout: 0
--> Created socket with soTimeout: 100
Got exception: java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketTimeoutException: Read timed out
java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
java.net.SocketTimeoutException: Read timed out
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:203)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:133)
at rmitest.RmiServer_Stub.rGetData(RmiServer_Stub.java:35)
at rmitest.RmiClient.main(RmiClient.java:19)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
at java.io.BufferedInputStream.read(BufferedInputStream.java:201)
at java.io.DataInputStream.readByte(DataInputStream.java:331)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:189)
... 3 more
To make short things short: this is what I should get without calling Thread.sleep(1) in my code. This "workaround" is not really a workaround, as if the RmiClient was a multithreaded application, I couldn't rely on sleeping to disable connection reuse. Is there any other way to prevent RMI connection reuse, then setting sun.rmi.transport.connectionTimeout to zero?