• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Implementin Unreferenced

 
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
ranger
Posts: 17347
11
Mac IntelliJ IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry,I push a wrong button.
continue
in my lock

Could any one explain it?
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It looks like you need to synchronize on lockRecords, and call notifyAll on it accordingly.
M
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Andrew Monkhouse
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 17347
11
Mac IntelliJ IDE Spring
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew, you're a rock star
M
[ July 18, 2003: Message edited by: Max Habibi ]
 
I suggest huckleberry pie. But the only thing on the gluten free menu is this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic