The Actual Distributed Garbage Collector The Unreferenced Interface

4. When the lease expires, if the client hasnt requested an extension, the distributed reference count is automatically decremented. Clients automatically try to renew leases as long as a stub hasnt been garbage collected. Given this, if we look at the problems with distributed reference counting, well see that the second and third problems have been neatly solved. If the client crashes, then the client application is no longer running, and therefore, the client application certainly isnt attempting to renew leases. Consequently, the lease wont be renewed, and the server is eventually garbage collected. Similarly, if network problems prevent the client application from connecting to the server, the client application wont renew the lease. In this case, the lease wont be renewed and the server will eventually get garbage collected. The default value of a lease is 10 minutes. This is configurable using the java.rmi.dgc.leasevalue property. Well discuss in more detail how to configure the default value, and why you would do so, later in this chapter.

16.2.4 The Actual Distributed Garbage Collector

The distributed garbage collector is an RMI server that implements the DGC interface, which is defined in the java.rmi.dgc package. This interface has only two methods: public void cleanObjID[] ids, long sequenceNum, VMID vmid, boolean strong public Lease dirtyObjID[] ids, long sequenceNum, Lease lease Both of these methods are automatically called by the clients runtime; you will never write code that calls either clean or dirty . c lean is called by the client runtime when it no longer needs a reference to a server. Strictly speaking, calls to clean are unnecessary™the client runtime can accomplish the same task by simply failing to renew the lease. However, leasing should be viewed as a last-gasp server cleanup mechanism, in place to lessen the damage caused by network or client failures. If you lengthen the duration of leases well discuss how to do this later, having well-behaved clients that notify servers when their references are no longer useful becomes enormously important. A client runtime requests a lease with dirty . It passes in a suggested lease and gets back the lease that the server is willing to grant. dirty doesnt need to pass a virtual machine ID VMID [ 1] directly because the instance of Lease that is passed in has a VMID. [ 1] A VMID is exactly what it sounds like: a unique identifier for a JVM. More precise details of the DGC interface arent very useful; weve covered enough that you will be able to customize the distributed garbage collectors behavior and read the RMI logs. Each JVM can have only one distributed garbage collector. Its important enough, and enough messages get sent to it, that it gets a special object identity: DGC_ID .

16.2.5 The Unreferenced Interface

The distributed garbage collector is responsible for maintaining leases. On the server side, when all the outstanding leases to a particular server object expire, the distributed garbage collector makes sure the RMI runtime does not retain any references to the server, thereby enabling the server to be garbage collected. During the process, if the server implements the Unreferenced interface, the server can find out if there are no longer any open leases. Unreferenced consists of exactly one method: public void unreferenced This can be useful when the server needs to immediately release resources instead of waiting for garbage collection to occur. It is also a convenient hook for persistence code™since the server knows that no remote methods will be called anymore, it can safely store its state to a more persistent medium e.g., a relational database. Well talk more about persistence in Chapt er 17 . For now, there are two important caveats to note. First, the RMI registry maintains leases on all the objects in it. Heres what the main method for our launch code looked like: public static void mainString[] args { int numberOfServers = Integer.valueOfargs[0].intValue ; NameRepository nameRepository= new NameRepositorynumberOfServers; Collection nameBalancePairs = getNameBalancePairsnameRepository; Iterator i = nameBalancePairs.iterator ; whilei.hasNext { AccountDescription nextNameBalancePair = AccountDescription i.next ; launchServernextNameBalancePair; } } Once main exits and it does, all the servers that were launched should go away. But they dont. This is because the RMI registry has stubs that refer to the servers. Therefore, the RMI runtime in the JVM running the registry keeps negotiating leases for the servers, and the distributed garbage collector keeps the servers alive. This is not some peculiar quirk of the RMI registry. Our naming service does the same thing. In general, if you have a stub, you have a lease. Thus, objects that are bound into either the registry or our naming service are reachable in the sense of the distributed garbage collector and will not be garbage collected. The second caveat is that unreferenced can be called more than once by the RMI runtime. Consider, for example, our naming services BaseContextImpl . Recall that an instance of BaseContextImpl creates instances of StubSender and StubSocketListener to handle the bootstrapping problem. Also recall that these objects create a thread that listens on an instance of ServerSocket . This means that BaseContextImpl is never garbage collected it is reachable from the thread that is listening on the instance of ServerSocket . However, if it implements Unreferenced , unreferenced would be called every time there were no active stubs. This could happen quite a few times.

16.3 RMIs Logging Facilities