This week's book giveaway is in the OCPJP forum.
We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line!
See this thread for details.
The moose likes Distributed Java and the fly likes Why does the RMI Reaper remove my object from the object table Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Distributed Java
Bookmark "Why does the RMI Reaper remove my object from the object table" Watch "Why does the RMI Reaper remove my object from the object table" New topic
Author

Why does the RMI Reaper remove my object from the object table

Nitesh Kant
Bartender

Joined: Feb 25, 2007
Posts: 1638

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 [0]
Mar 26, 2007 2:27:26 PM sun.rmi.transport.ObjectTable removeTarget
FINER: RMI Reaper: remove object [0]

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 ]

apigee, a better way to API!
Edward Harned
Ranch Hand

Joined: Sep 19, 2005
Posts: 291

registry.rebind("nitesh", testRemote);

rebind testRemote not remoteStub

You bind the implementation code (remote object), not a stub.


Ed's latest article: A Java Parallel Calamity http://coopsoft.com/ar/Calamity2Article.html
Nitesh Kant
Bartender

Joined: Feb 25, 2007
Posts: 1638

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.
Nitesh Kant
Bartender

Joined: Feb 25, 2007
Posts: 1638

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.
Edward Harned
Ranch Hand

Joined: Sep 19, 2005
Posts: 291

GC is always a problem.

Save a reference to your implemented class in your start up method/class.

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.

Thanks for the research.
Nitesh Kant
Bartender

Joined: Feb 25, 2007
Posts: 1638

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
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Why does the RMI Reaper remove my object from the object table