Hi, I have the following sample code to bind a test remote object to the RMI registry
Now, when i run the above program with the following parameters: -Dsun.rmi.loader.logLevel=VERBOSE -Dsun.rmi.dgc.logLevel=VERBOSE I get the following log: Mar 26, 2007 2:27:26 PM sun.rmi.transport.WeakRef pin FINER: main: strongRef = sun.rmi.transport.DGCImpl@17a8913 Mar 26, 2007 2:27:26 PM sun.rmi.transport.ObjectTable putTarget FINER: main: add object [0:0:0, 2] Mar 26, 2007 2:27:26 PM sun.rmi.transport.WeakRef pin FINER: main: strongRef = RegistryImpl[UnicastServerRef [liveRef: [endpoint:[10.10.2.67:1098](local),objID:[0:0:0, 0]]]] Mar 26, 2007 2:27:26 PM sun.rmi.transport.ObjectTable putTarget FINER: main: add object [0:0:0, 0] Mar 26, 2007 2:27:26 PM sun.rmi.transport.ObjectTable putTarget FINER: main: add object  Mar 26, 2007 2:27:26 PM sun.rmi.transport.ObjectTable removeTarget FINER: RMI Reaper: remove object 
If you see the last log, it indicates that the RMI Reaper thread has removed an object. However, it does not give the detail of the object removed but i assume that it is the object that i have added because, when i try to execute a method on the object that i have bound(by name "nitesh") i get the following exception:
Exception in thread "main" java.rmi.NoSuchObjectException: no such object in table at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:179) at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132) at $Proxy0.hello(Unknown Source)
Is it so, that the RMI reaper has removed the bound object from the object table, as soon as it is bound? Just to mention, the above exception come while calling the method hello on the remote interface. I can lookup the object from the registry. Also, i am not generating any stubs, so dynamic proxy will be used in this case.
I am sure i am missing something.
Just a nasty fact. If i make this thread sleep for some time just before the bind to the registry, everything works fine .... can somebody help me understand this
code for the remote interface, implementation and client for reference:
[ March 26, 2007: Message edited by: Nitesh Kant ]
Originally posted by Edward Harned: registry.rebind("nitesh", testRemote);
rebind testRemote not remoteStub
You bind the implementation code (remote object), not a stub.
Hi Edward, Actually, thats how i learned RMI too Actually, all this came from this sun tutorial trail One of my friend was going through this and asked me to give a reason for the same :roll: The tutorial, clearly specifies that the stub is bound to the registry. So, i was confused. Actually, binding the remote object works fine but i just wanted to know the reason as to why this is happening with the stub, as the stub is also a remote object anyways.
Phew, i got the answer .... Actually, the object created in
was getting garbage collected I had the following findings:
1) The problem was not with the registry.bind(). 2) The problem was with the export. 3) Since i was exporting the above mentioned implementation which was going out of scope and was getting garbage collected, so, it was also removed from the ObjectTable. ObjectTable holds a reference queue for the weak reference of the object being exported. So, as soon as it was GCed, it was removed from the object table.
Now, few findings on the difference between binding the stub and the object itself to the rmi registry: 1) When i bind the actual object implementation with the registry, then, the rmi registry holds a remote reference to my server implementation, so by the laws of DGC, this will not be garbage collected. 2) When i bind the stub to the registry, then the rmi registry holds a remote reference to this stub and not of the actual object implementation and so it will be garbage collected.
Also, about the nasty fact ... as to why a Thread.sleep() in the callMe() method makes everything run nicely. This is so because a Thread.sleep() made the GC to run with the method still executing and the object implementation still in scope. So the GC did not collect the object. I confirmed this by printing the verbose GC messages!!! Also, i called System.gc() after the callMe() method returned. That collected the object and subsequently, it got removed from the ObjectTable.
Ranchers, (if anyone listening) do let me know if any of the above findings are wrong.
Originally posted by Edward Harned: GC is always a problem.
Save a reference to your implemented class in your start up method/class.
Yeah thats what i did!
To avoid GC, I always issue a never ending wait() in the the start-up class. Since there are keep alive threads in RMI, the server needs to issue a System.exit() when it wants to end.
Actually, do we need this? May be i am wrong. I think if you just make the implementation a static variable in the start-up class, it should work. It will not be GCed till the class is unloaded from the VM i.e. essentially when the classloader gets garbage collected. But, yeah a never ending wait() will make sure that whatever may come .. i will be alive