wood burning stoves 2.0*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Implementin Unreferenced Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Implementin Unreferenced" Watch "Implementin Unreferenced" New topic
Author

Implementin Unreferenced

Akshay Sharma
Ranch Hand

Joined: Mar 27, 2003
Posts: 42
It seems to me that merely implementing the Unreferenced interface is not enough for receiving notification of no more live references to a remote server object. In the following "Hello" example, the class HelloImpl implements the Unreferenced interface and provides an implementation for its unreferenced() method. Yet this method is never invoked even long after the client has stopped interacting with the server.
The RMI Specification document says: "As long as some client holds a remote reference to the remote object, the RMI runtime keeps a local reference to the remote object. When the "reference" set becomes empty, the Unreferenced.unreferenced method is invoked (if the server implements the Unreferenced interface)."
But the following example shows that the meaning one would ordinarily give to these statements in the RMI specification document is not valid.

///////// server file: Hello.java ////////
import java.rmi.*;
public interface Hello extends Remote {
public String sayHello() throws RemoteException;
}

/////// server file: HelloImpl.java ////////
import java.rmi.*;
import java.rmi.server.*;
import java.net.*;
public class HelloImpl extends UnicastRemoteObject
implements Hello, Unreferenced {
public HelloImpl() throws RemoteException {}
public String sayHello()
{
String hostname = null;
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch( java.net.UnknownHostException un ) {}
return "Hello from Avi Kak at " + hostname;
}
public void unreferenced()
{
System.out.println( ">>>> No clients holding remote references <<<" );
}
}
///////// server file: HelloServer.java ////////
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
public class HelloServer {
public static void main( String[] args )
{
try {
LocateRegistry.createRegistry( 1099 );
HelloImpl helloserver = new HelloImpl();
Naming.rebind( "rmi://localhost/HelloServer", helloserver );
} catch( Exception e ) {}
}
}

///////// client file: HelloClient.java ///////
import java.rmi.*;
public class HelloClient {
public static void main( String[] args )
{
try {
Hello server = ( Hello ) Naming.lookup( "rmi://RVL4.ecn.purdue.edu/HelloServer" );
System.out.println( server.sayHello() );
} catch( Exception e ) {}
}
}

***********************
I have also tried playing with the leaseValue but that does not help.
So what do I do to get instant notification of the fact that a client has disconnected.


Akshay Kumar Sharma<br />**********************<br />Good Better Best <br />Never Let it rest<br />For your good is better<br />and the better is the best
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17249
    
    6

Well in your example, the client has ended, not crashed. So the remote reference is removed through the normal RMI process. Unreferenced will not be called in that case.
Mark


Perfect World Programming, LLC - Two Laptop Bag - Tube Organizer
How to Ask Questions the Smart Way FAQ
Max Habibi
town drunk
( and author)
Sheriff

Joined: Jun 27, 2002
Posts: 4118
I don't think that's the problem. The java RMI spec is pretty clear that Unreferenced gets called whenever the references to the remote object drop to 0: it says nothing at all about Exceptions.

The java.rmi.server.Unreferenced interface allows a server object to receive notification that there are no clients holding remote references to it. The distributed garbage collection mechanism maintains for each remote object, the set of client virtual machines that hold references to that remote object. As long as some client holds a remote reference to the remote object, the RMI runtime keeps a local reference to the remote object. Each time the remote object's "reference" set becomes empty (meaning that the number of clients that reference the object becomes zero), the Unreferenced.unreferenced method is invoked (if that remote object implements the Unreferenced interface). A remote object is not required to support the Unreferenced interface.
As long as some local reference to the remote object exists, it may be passed in remote calls or returned to clients. The process that receives the reference is added to the reference set for the remote object. When the reference set becomes empty, the remote object's unreferenced method will be invoked. As such, the unreferenced method can be called more than once (each time the set is newly emptied). Remote objects are only collected when no more references, either local references or those held by clients, still exist.

I first I though it was because he's playing with Strings, because they get GC'd differently then other objects. But that's not the issue. Then I thought it was because the local server variable, helloserver was maintaining a reference, so I nulled it out. Still didn't work. I'm stumped. I'll continue to look into it.
M


Java Regular Expressions
Ray Cheeny
Ranch Hand

Joined: Aug 21, 2002
Posts: 74
Hi friends,
In my unreferenced(),I got some exceptions when it is called.
java.lang.IllegalMonitorStateException: current thread not owner
why?
my unreferenced() is like:
Ray Cheeny
Ranch Hand

Joined: Aug 21, 2002
Posts: 74
Sorry,I push a wrong button.
continue
in my lock

Could any one explain it?
Max Habibi
town drunk
( and author)
Sheriff

Joined: Jun 27, 2002
Posts: 4118
Hi Ray,
I'm not sure what you're calling notifyAll on, but you need to synchronize on whatever it is.
M
Ray Cheeny
Ranch Hand

Joined: Aug 21, 2002
Posts: 74
Hi,
I think when clientA is crashed and still has the lock on record1. ClientB have to wait for record1. When unreferenced() is called, it clears all the locks. So I call notifyAll() to notify ClientB.
Is that right?
Max Habibi
town drunk
( and author)
Sheriff

Joined: Jun 27, 2002
Posts: 4118
It looks like you need to synchronize on lockRecords, and call notifyAll on it accordingly.
M
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Within refreshAll(), just synchronize on "this". Or jsut make refreshAll() a synchronized method. You Can't call wait(), notify(), or notifyAll() unless you've synchronized on the instance whose method you're invoking - that's "this" when you don't explicitly name the object.
Incidentally your comment "Exception is thrown here" is almost certainly incorrect. Double check the line number. This may indicate that the source code you're looking at isn't the version that's actually being executed. If you're not using an UDE that takes care of this for you, it's a good idea to get in the habit of deleting all old class files before you compile. This is easy to do with ant or a shell script.


"I'm not back." - Bill Harding, Twister
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11404
    
  81

Hi Akshay
Max and Mark: you are going to kick yourselves over this
The reason unreferenced is not called in your code is because the rmiregistry is still holding a reference to it.
The following code will show you unreferenced being called immediately that the client code finishes. If you want the lease time to come into play, remove the call to the garbage collector in the client code. Then the lease time (that I set to 10 seconds) will have to expire before unreferenced is called:

Note that there are two remote objects in this program - so you have to run rmic against both:

I vaguely remember from another thread, Max described a different way of having a connection factory.
My method (as above) is to have a class that provides instances of my Server class as required.
The alternative suggested by Max (if I remember correctly) was to have a new Server class bound to the registry as the existing one gets used by a remote client.
Trouble is - although the reason for this made sense at the time, I cannot remember why Max was advocating it.
Max - any comments?
Regards, Andrew


The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11404
    
  81

Just to add a bit more.
In my sample code, it is only the Server class that implements Unreferenced. The Server class is never bound in the rmiregistry, so the rmiregistry does not have a reference to it. It is only the client code that ever gets a reference to an instance of the Server, so once the client code releases it's reference, then unreferenced is called.
And from the Frequently Asked Questions RMI and Object Serialization

D.3 Is it possible for a remote object to be notified when all clients disconnect?
Yes. Your remote object will need to implement the java.rmi.server.Unreferenced interface (in addition to any other necessary interfaces). RMI will provide the notification by calling the unreferenced method when all clients disconnect. Your implementation of the unreferenced method will determine what action your remote object should take upon receiving such a notification. However, if there is a reference in the registry, then the Unreferenced.unreferenced method will never be called.

(Highlighting was mine)
Regards, Andrew
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17249
    
    6

Yes that is true. He has bound the remote object that he is referring too. In our design the Remote objects that are implementing Unreferenced are not bound to the registry, and that is why it works.
Since the object is in the registry, there is still a reference to the object and therefore Unreferenced is not called. Good find Andrew. I obviously didn't look at the code that well.
Mark
Max Habibi
town drunk
( and author)
Sheriff

Joined: Jun 27, 2002
Posts: 4118
Andrew, you're a rock star
M
[ July 18, 2003: Message edited by: Max Habibi ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Implementin Unreferenced
 
Similar Threads
Not Finding Stub
RMI access denied client/server
Error while registring the server object to RMI registry
RMI Example
exception in client side