• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

unreferenced Never called

 
Melinda White
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,
I have read every post I can find here on this problem and still am unable to resolve it. Perhaps someone has an idea how I can debug this?
I set up an ant target that instantiates 5 clients and modifies the seat count on the same flight. I verified that the seat count is modified correctly, but the problem is that unreferenced is never called - not even when I set the client's reference to the remote object to null.
In my startServer.bat I set the lease time and the check interval to 20 seconds each with the following line: (no line returns in this single line)
java -Djava.rmi.dgc.leaseValue=20000 -Dsun.rmi.dgc.checkInterval=20000 suncertify.server.ServerMain

I've tried forcing the clients to sleep a long time to force the lease to expire, and unreferenced still does not get called!
Does my java command line look ok?
Anyone know how to debug this? I've tried writing to a log file instead of printing to System out, I've tried to capture each clients stdout and stderr, but I get no errors. In fact, I get output indicating that the remote reference has been set to null before my ClientMain class exits. I do System.gc(), but is there a way to force dgc?

I do know that one time many weeks ago (before I started working 10 hour days) I saw output ONCE to the effect that unreferenced got called, so I suspect my inheritance of RMI objects is ok.

Many thanks in advance.
 
Peter den Haan
author
Ranch Hand
Posts: 3252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please don't be offended if I ask the obvious -- it needs to be asked
  • Is your class implementing Unreferenced?
  • Are you sure you every single one of your client-side references to the object? The client will keep on renewing the lease while one is around.
  • Are you sure each client gets a different remote object?
  • The client-side RMI code won't know that you dropped all references until the garbage collector has done its job. Try prodding it with System.gc().
  • What happens if the client simply exits?
  • What happens if you kill your client (using the Windows task manager or Unix' kill command)?
  • HTH,
    - Peter
     
    Melinda White
    Greenhorn
    Posts: 25
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi Peter,
    Thanks very much for your response. I've been stuck on this stupid problem for too long.
    Here are answers to your very good questions.
    Q: Is your class implementing Unreferenced?
    A: yes
    Q: Are you sure you every single one of your client-side references to the object? The client will keep on renewing the lease while one is around.
    A: Do you mean does every client release its reference? If so, yes, I set it to null and then do System.gc() on the client side. I see from my debug output that this happens ok.
    Q: Are you sure each client gets a different remote object?
    A: Well - tell me if I have this right. There is only one object (dataAccess) that is registered on the server side. Each client gets a handle to this interface object. Then each client sets this handle to null after it is finished doing its data access work (in this case, booking seats). Is this implented correctly, or do I need to register a remote object for each instance of the client that wants a handle?
    Q: The client-side RMI code won't know that you dropped all references until the garbage collector has done its job. Try prodding it with System.gc().
    A: I tried that on the client side.
    Q: What happens if the client simply exits?
    A: I set the remote object to null, do System.gc(), and unreferenced is never called.
    Q: What happens if you kill your client?
    A: I will try this.
    Thanks again for your help.
    Melinda
     
    Mark Spritzler
    ranger
    Sheriff
    Posts: 17278
    6
    IntelliJ IDE Mac Spring
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    When you set the remote instance to null you are cleaning up, that is not the purpose of Unreferenced.
    The purpose is to handle when the client crashes.
    So you have to abort the client while the remote object still exists. Remember that the default time for Unreferenced is 10 minutes.
    Mark
     
    Peter den Haan
    author
    Ranch Hand
    Posts: 3252
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Unreferenced should be called whenever all remote references to an object have gone -- whether that is through setting them to null, or through a crash. Of course it is likely to take longer after a crash because you'll have to wait for the lease to expire
    Melinda, could your problem be that all clients share one and the same server-side object? Unreferenced will only be called when all clients have released their reference, every single one of them.
    The approach taken by many in the group (including yours truly) is to give each client their own, unique server-side Connection object. This object itself then identifies the client, and when that client crashes or drops the reference without nicely close()ing the Connection, we can use the Unreferenced mechanism to clean up. But this only works because each client has its own object, and nothing else maintains a (remote) reference to it.
    - Peter
     
    Melinda White
    Greenhorn
    Posts: 25
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks Mark and Peter,
    My understanding is that unreferenced should clear all locks held by the client that crashed or otherwise ended "normally" but may have left locks open.
    Peter, you raise a good question and perhaps I need to do more research. There is a possibility that all clients are using the same remote object and so when one client dies or ends normally, unreferenced is not called because other clients are keeping the reference. But even when all of my clients end normally (thus setting the handle to null and calling System.gc()) -- or even when I run only ONE client --, unreferenced is still not called.
    (By the way, the object is DataAccessRemote and the handle is to an interface that implements my IDataAccess interface that is also implemented by DataAccessLocal.)
    I am aware of the normal time limits on the lease time and the check interval. I tried setting them both to 20 seconds, but it seems to have no affect.
    Anyone know a good RMI book?
    Thanks a lot all for your help. I am stumped.
    Melinda
     
    Peter den Haan
    author
    Ranch Hand
    Posts: 3252
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Melinda White:
    My understanding is that unreferenced should clear all locks held by the client that crashed or otherwise ended "normally" but may have left locks open.
    Many do this because it's neat and easy to do, but I do not believe there is a requirement to do this. If it's driving you up the wall you can always not do it.
    Do document this as a "design decision" so the assessor knows you have thought about it. Something along the lines of your expectation that the FBN application holds locks only very briefly, which makes the critical window and thereby the risk so small that a cleanup mechanism is not worth the effort.
    Anyone know a good RMI book? [...] I am stumped.
    Michael Ernest recommends The Remote Method Invocation Guide highly. See his review in the Bunkhouse.
    Based on the inevitably limited picture I have of what you're doing, I'm stumped too. I wish I could offer to take a look at your code, but I have a book deadline on the 8th and have to present a session at UKOUG 2002 on the 10th, so dipping into the forums is already more than I ought to do :roll:
    - Peter
    [ December 03, 2002: Message edited by: Peter den Haan ]
     
    Reinhold Gruber
    Greenhorn
    Posts: 12
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi!
    I think the problem is that your DataAccess-Object which implements Unreferenced is bound into the RMI registry. Because the registry is by itself a remote Object, there will always be a remote reference to DataAccess as long as the registry is running and therefore no unreferenced()-call will happen.
    Reinhold
     
    Melinda White
    Greenhorn
    Posts: 25
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks very much for the book recommendation and all the help. I really want to figure this out because I did see it work ONCE a few weeks ago - don't remember how I reproduced it.
    Peter, I appreciate all your help and would feel it an imposition for you to look at my code anyway, even if you did have time.
    Well, if this were easy everyone would do it, rigtht?
    Thanks all,
    Melinda
     
    Peter den Haan
    author
    Ranch Hand
    Posts: 3252
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Reinhold Gruber:
    I think the problem is that your DataAccess-Object which implements Unreferenced is bound into the RMI registry. [...]
    Whoa! That is a very good point -- thanks, Reinhold. It didn't dawn on me that you could be binding these things in the registry, but if you are, then yes... Melinda?
    - Peter
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic