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.
- 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.
- Since serialization involves the serialization of the whole
object graph, the operation may be expensive.
- 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.
- 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
- acts as a client's proxy for the remote object.
- implements the same set of remote interfaces that the remote object
implements.
The functions of the stub are
- initiate a connection with the remote VM containing the remote object
- marshal (write and transmit) the parameters of the remote VM
- wait for the result of the method invocation
- unmarshal (read) the return value or exception returned
- 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
- unmarshal the parameters for the remote method
- invoke the method on the actual object implementation
- 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.
- 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.
- Code signing: If the applet is signed, then full access to the
system resources is provided (if the signature is trusted).
- 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