Interfaces

Recall that an ADT consists of an interface and an implementation. Usually the interface is the public part of a class and the implementation is the complete defintion of the class. Java provides the mechanism of interfaces to make a cleaner separation.

An interface is an expression of pure design. (A class is a mix of design and implementation.) All the methods in an interface are abstract. All the fields in an interface are static and final.

While interfaces cannot be instantiated, one can have objects of the interface class. In this way, multiple implementations can be mixed.

interface Set {
   String printSet();
}

class Set1 implements Set {
   public String printSet() { return "Set1"; }
}

class Set2 implements Set {
   public String printSet() { return "Set2"; }

   public statc void main(String[] args) {
         Set s1, s2; // Note

         s1 = (Set) new Set1(); // using two different implementations
         s2 = (Set) new Set2();
   }
}

Serialization

The I/O of objects raises several issues.
  1. Explicit I/O by programmer is difficult since each object is actually a graph and not a tree. It is difficult for the programmer to handle the graph. Consider, for example, an array of Objects. It is possible that two entries refer to the same object. When serializing this object, only one copy of the should be serlialized.
  2. Since serialization involves the serialization of the whole object graph, the operation may be expensive.
  3. Automatic I/O by the system is difficult since it may not make sense to serialize some fields. For example, while file names can be serialized, file handles should not be.
  4. Serialization and security are antithetical. Since all the fields of the object should be serialized (including private) fields, the resulting serialized object loses the security guarantee.
In Java, objects are not serialized by default. If the programmer wants objects of a class to be serialized, the class should be marked as implements java.io.Serializable. Fields which should not be serialized should be marked transient. Methods writeObject() and readObject() of classes ObjectOutputStream and ObjectInputStream can be used to serialize and deserialize objects.

Serialization involves some issues. Consider the folowing hierarchy.

                A
                |
                v   Serializable
                B   /
                |  /
                v /
                C/
                |
                v
                D
How are the fields of A and B serialized? In this case, class C should provide its own implementation for serializing these fields.

RMI issues

      Client          Server
        ^               ^
        |               |
        v               v
+----------------+-----------------+
|   Stubs        |    Skeletons    |
+----------------+-----------------+
|   Remote reference layer         |
+----------------------------------+
|   Transport layer                |
+----------------------------------+

Stubs and skeletons

The stub and skeleton are generated by rmic at the server side. The client gets the stub through lookup at the registry. The stub
  1. acts as a client's proxy for the remote object.
  2. implements the same set of remote interfaces that the remote object implements.
The functions of the stub are
  1. initiate a connection with the remote VM containing the remote object
  2. marshal (write and transmit) the parameters of the remote VM
  3. wait for the result of the method invocation
  4. unmarshal (read) the return value or exception returned
  5. return the value to the caller
The stub hides the serialization of parameters and the network-level communication in order to present a simple invocation mechanism to the caller.

The skeleton is responsible for dispatching the call to the actual remote object implementation. The functions of the skeleton are

  1. unmarshal the parameters for the remote method
  2. invoke the method on the actual object implementation
  3. marshal the result (return value or exception) to the caller

Dynamic class loading

When more information is needed about the object, for example, the run for its method, the class file is loaded dynamically (at runtime).

Concurrency

What happens when serveral clients contact the server at the same time? Each connection starts a thread. The synchronization of these threads should be handled by the object itself.

The other model for this is to honor the requests one by one. Java does not follow this model. The Ada model of message passing is more restricted. The server should restart (in some sense). (Notes on concurrency in Ada.) It is not fair to compare Ada tasks with RMI. The Ada model is meaningful in the context of processes. RMI is meaningful in the context of network communication.

Security

Note that both the server and the client execute foreign code. (The client executes the stub and the server the code provided by the client.) To prevent the possibility of executing malicious code, runtime security checks are needed. Java provides several models of security.
  1. Sandbox model: This is the original model of security for Java applets. The code executes in a "sandbox" - it cannot open files and it can make network connections only to its home site.
  2. Code signing: If the applet is signed, then full access to the system resources is provided (if the signature is trusted).
  3. Policy based security: Here security is more fine grained. The user can set up permission for sockets, threads, file systems, windows, etc. individually. The following is an example policy file which grants all permissions to code signed by "sysadm", but only file read permissions to the file ~/.plan.
    grant signedBy "sysadm" {
        permission java.security.AllPermission;
    }
    
    grant {
        permission java.io.FileReadPermission "~/.plan";
    }
    

Exceptions

Notes