Ordinary Garbage Collection Distributed Garbage Collection

Most servers in ordinary use have randomly assigned instances of ObjID . However, there are three reserved identifiers: ACTIVATOR_ID , DGC_ID , and REGISTRY_ID . These three IDs correspond to the three main servers that RMI provides: the activation framework, the distributed garbage collector, and the RMI registry. Well talk about the distributed garbage collector later in this chapter and the activation framework in Chapt er 17 . The RMI registry needs a unique identifier, which is known in advance, in order to fully solve the bootstrapping problem. Recall that the RMI runtime tries to reuse sockets. RMI servers, even the registry, do not get dedicated sockets. But now consider a client attempting to connect to the RMI registry for the first time. Unless it already knows the object identity associated with a server, a client cannot send a message to that server. That is, since the servers RMI runtime requires an instance of ObjID in order to determine the appropriate server for a request, the client needs to know the ObjID of the registry running in the servers JVM in order to connect to the registry. In order to solve this problem, the designers of RMI decided to define a special instance of ObjID that is reserved™if a registry is running in a JVM, it uses REGISTRY_ID . Otherwise, no server is allowed to use REGISTRY_ID . This solves the RMI bootstrapping problem. The static methods defined in the Naming class take a string that contains the address of a computer on the network and a port; the only additional information needed to construct a stub is the object ID of the server to which the stub connects. Since the registry always uses REGISTRY_ID , a stub for the registry can be constructed entirely on the client side, before connecting to the registry. This strategy also means that there can only be one registry exported per JVM, since ObjID s cannot be shared by more than one server. In comparison, we solved the bootstrapping problem for the naming service implemented in Chapt er 15 by defining a second, more primitive protocol that was used only to establish initial connections. Each instance of BaseContextImpl had both its RMI behavior achieved by extending UnicastRemoteObject and a second port, which it used to vend stubs. This second port used a dedicated server socket that enabled our instances of BaseContextImpl to bypass the preceding problem. Since the message that establishes the initial connection doesnt go through RMI, the client doesnt need to know the identity of the BaseContextImpl in advance.

16.2 Distributed Garbage Collection

Another one of the three fixed object identifiers is DGC_ID . This is the object identifier associated with the distributed garbage collector built into RMI. The distributed garbage collector is useful and important in distributed applications built using RMI. Its also not very complicated. Before describing how the distributed garbage collector works, however, I will spend a few paragraphs explaining ordinary garbage collection.

16.2.1 Ordinary Garbage Collection

The motivation for garbage collection is simple: memory management is hard. Programmers are very good at creating new objects. But knowing when to release an object is much more difficult. Consider, for example, the following snippet of Java code: public Money getBalanceString clientIDNumber throws RemoteException, LockedAccountException { checkAccessclientIDNumber; return _balance; } The problem is that, without some form of automatic memory management, programmers must somehow decide when _balance is freed. A consistent policy must be adopted across the entire codebase. Any failure, anywhere in the code, to abide by and enforce the policy, can lead to a memory leak. One such policy, for example, is: If a method returns an object, the returned object is the responsibility of the caller. The object whose method was called should not retain any references to returned objects. This policy is easy enough to implement; it changes the preceding method into: public Money getBalanceString clientIDNumber throws RemoteException, LockedAccountException { checkAccessclientIDNumber; Money returnValue = new Money_balance; return rreturnValue; } However, this has two sizable flaws. The first is that it leads to the creation of a lot of objects in cases where you dont really need to create objects. The second is that you cant actually universally adhere to this solution. You cannot simply make a copy of a socket or a file. Of course, you can then create an addendum to the preceding policy, something like: Unless, of course, the returned object is a special object such as a socket or a file; special objects are treated according to the following rules... Garbage collection is a much simpler solution. The basic idea is to define a set of reachable objects and then discard objects that are not reachable the garbage. Reachable objects are defined recursively: • Each active thread is currently in a method, in an instance of an unknown object. These instances, which threads are actually in, are reachable. • Theres a small set of objects that each thread can immediately find: the objects referenced by the method-level variables and the instances fields. These objects are also reachable. • From each of these immediately accessible objects, there are other objects that can be reached. • And so on. In general, if a thread, starting from where it is currently, can eventually find an object, that object is reachable. Given the definition of reachable objects, any garbage collection algorithm does three things: • It either maintains an index of, or knows how to find out about, the set of all currently allocated objects. • It occasionally computes the set of objects that are reachable from the active threads. • It reclaims garbage collects objects that are not reachable. This neatly solves the problem of when to free objects. We can use the first version of the code: public Money getBalanceString clientIDNumber throws RemoteException, LockedAccountException { checkAccessclientIDNumber; return _balance; and rely on the system to free _balance when _balance is no longer reachable.

16.2.2 Defining Network Garbage