Download Java RMI - Software Architecture Document

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Java RMI - Software Architecture Document
Vladimir Smatanik
[email protected]
Richard Dérer
[email protected]
Jacek Marek
[email protected]
Alexandru Dimitriu
[email protected]
Department of Information and Computing Sciences,
Utrecht University,
January 13, 2011
1
Contents
1 System Description
1.1 Introduction . . . . . . . . . . . . . . . . .
1.1.1 What is Remote Method Invocation
1.2 Architecture . . . . . . . . . . . . . . . . .
1.2.1 Interfaces . . . . . . . . . . . . . .
1.2.2 RMI Architecture Layers . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2 RMI Overview
2.1 Localization of remote objects . . . . . . . . . . . .
2.2 Communication with remote objects . . . . . . . .
2.3 Loading class bytecodes for objects that are passed
values . . . . . . . . . . . . . . . . . . . . . . . . .
2.4 Garbage collection of remote objects . . . . . . . .
2.5 RMI communication through firewalls . . . . . . . .
2.6 Remote object activation . . . . . . . . . . . . . . .
2.7 Enhance Java RMI with security . . . . . . . . . .
2.7.1 Secure network connection with policies . .
2.7.2 Encrypt network connection . . . . . . . . .
2.7.3 Enable authentication . . . . . . . . . . . .
2.7.4 Transactions . . . . . . . . . . . . . . . . . .
2.8 RMI-IIOP . . . . . . . . . . . . . . . . . . . . . . .
2.8.1 Before RMI-IIOP . . . . . . . . . . . . . . .
2.8.2 After RMI-IIOP . . . . . . . . . . . . . . . .
2.8.3 Development procedure . . . . . . . . . . . .
3 Quality aspects addressed by the system
3.1 ISO/IEC 9126-1 . . . . . . . . . . . . . .
3.2 Efficiency . . . . . . . . . . . . . . . . .
3.2.1 Performance . . . . . . . . . . . .
3.2.2 Resource utilization . . . . . . . .
3.3 Functionality . . . . . . . . . . . . . . .
3.3.1 Security . . . . . . . . . . . . . .
3.4 Maintainability . . . . . . . . . . . . . .
3.5 Usability . . . . . . . . . . . . . . . . . .
4 Architectural View
4.1 Service registering . . . . . . .
4.2 Client-server communication .
4.3 Distributed garbage collection
4.4 Java RMI with threads . . . .
4.5 Remote exceptions handling .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . .
. . . . . . . .
as parameters
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
4
4
4
5
7
7
8
. . . . . .
. . . . . .
or return
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
8
9
9
10
11
11
11
11
11
12
12
12
13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
14
14
14
15
15
15
15
16
.
.
.
.
.
17
17
17
18
19
22
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4.6
4.7
Role of the JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Scenario view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
25
5 Technical Aspects
5.1 Security manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Handling sockets with socket factories . . . . . . . . . . . . . . . . . . . . . .
5.3 Remote objects inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
26
27
29
6 Alternate Systems
6.1 RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.1 General description . . . . . . . . . . . . . . . .
6.1.2 Architecture . . . . . . . . . . . . . . . . . . . .
6.1.3 Comparison with RMI . . . . . . . . . . . . . .
6.1.4 Usability vs. maintainability & performance . .
6.1.5 Performance comparison . . . . . . . . . . . . .
6.1.6 Security issues . . . . . . . . . . . . . . . . . . .
6.1.7 Summary . . . . . . . . . . . . . . . . . . . . .
6.2 CORBA . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2.1 General description . . . . . . . . . . . . . . . .
6.2.2 Architecture . . . . . . . . . . . . . . . . . . . .
6.2.3 Architectural trade-offs of CORBA & Java RMI
6.2.4 Performance . . . . . . . . . . . . . . . . . . . .
6.2.5 Summary . . . . . . . . . . . . . . . . . . . . .
31
31
31
31
32
32
33
34
34
34
34
35
35
36
37
7 Q&A
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
38
3
1
1.1
System Description
Introduction
Java Remote Method Invocation (Java RMI) allows the programmer to create distributed
Java technology-based applications.
Distributed systems need to be able to communicate, because the computations are taking
place in different address spaces, potentially on different hosts. In Java, the basic communication is supported with sockets. Sockets are a good option for general communication.
Because of the low-level nature of sockets, the client and server are forced to engage in
application-level protocols to encode and decode messages for exchange. Avoiding designing
such protocols is desirable, because it is cumbersome and can be error-prone.
1.1.1
What is Remote Method Invocation
The alternative to sockets is Remote Procedure Call (RPC). RPC abstracts the communication interface to the level of a procedure call. It gives the programmer an illusion that he
is calling a local procedure but in fact, he is communicating with remote target of the call.
So the programmer does not directly work with sockets.
In order to match the semantics of object invocation the distributed object systems require remote method invocation. Under RMI, entire objects can be passed and returned as
parameters, unlike many RPC. In RPC, only primitive data types or structures composed
of primitive data types can be used as a return values or parameters.
This means every Java object can be an argument, or a return value. Even objects that
have never been encountered by remote virtual machine. The only condition that must be
met is that the object is serializable.
1.2
1.2.1
Architecture
Interfaces
There is one essential concept of RMI. Definitions of behaviors are separate from the implementation of those behaviors. Code that defines behavior and code that implements the
behavior are separate and can execute on separate JVMs.
4
In distributed systems, clients are concerned about the definition of a service and servers
are focused on providing that service. To be exact, definition, or in another words behavior
of a remote service, is implemented with Java interfaces. The implementation of the remote
service is implemented using classes.
Interfaces do not contain executable code. RMI supports two classes for implementation
of the interface. First class is the implementation of the behavior that runs on the server.
Second class acts as a proxy for the remote service and it runs on the client (this is called a
service stub in RMI terminology).
Figure 1: Interface, implementation
1.2.2
RMI Architecture Layers
The RMI is built from three abstraction layers.
Figure 2: Architecture layers
1. Stub and Skeleton layer
This layer lies right under the view of developer. The purpose of this layer is to
intercept method calls made by the client to the interface reference variable and to
redirect these calls to a remote RMI service.
5
For the better understanding of RMI, it is important to focus on this layer. RMI uses
standard mechanism for communicating with remote objects employed in RPC systems:
stub and skeleton. A stub is the client’s local representative of a remote object. In
other words, it is the the proxy for remote object. Stub hides all the network-level
communication and serialization of parameters in order to present a simple invocation
mechanism to the caller. When the caller invokes a method on the local stub, this
stub is responsible for carrying out the method call on the remote object. The stub
implements the same set of remote interfaces a remote object implements.
Skeleton works on the server side. Each remote object may have a skeleton (in Java
2 platform-only environments, skeletons are not explicitly required and are embedded
in RMI server logic). This skeleton is responsible for directing the call to the actual
implementation object.
In Java 2 SDK Standard Edition version 1.2 an additional stub protocol was introduced that eliminates the need for skeletons in Java 2 platform-only environments.
Instead, generic code is used to carry out the duties performed by skeletons in JDK
1.1. Stubs and skeletons are generated by the rmic compiler.
2. Remote Reference Layer
This layer is the middleware between the stub & skeleton layer and the underlying
transport layer. This layer handles the creation and management of remote object
references. It also connects clients to exported objects that are running on the server.
Connection is a one-to-one (unicast) link. In Java 2 SDK, this layer was enhanced to
support the activation of dormant remote service objects via Remote Object Activation.
3. Transport layer
The transport layer is based on TCP/IP connections between machines on the network. It provides basic connectivity, as well as some firewall penetration strategies.
All connections are stream-based network connections that use TCP/IP. Even if two
JVMs are running on the same physical computer, they connect through their host
computer’s TCP/IP network protocol stack.
6
2
RMI Overview
RMI helps us with the development of applications that often consist of two separate
programs: a server and a client.
A typical server application creates a number of remote objects. These objects are then
exported, which means the references are made accessible. Finally the server waits for clients
to invoke methods on those remote objects.
A typical client application gets the remote reference to one or more remote objects in the
server. Through these references client invokes methods on the remote objects.
RMI provides the mechanism by which the server and the client communicate and pass
information back and forth. This kind of application is referred as a distributed object
application. Distributed object applications need to take care of the following:
2.1
Localization of remote objects
Two basic mechanisms are provided by RMI to locate remote services. The most common
is naming or directory service. An important question to ask here would be as follows: “how
can a client locate a remote service by using another service?” It is possible because the
naming or directory service runs on a well-known host and port number, therefore, client
can directly access it’s register to locate any service on the network. The second mechanism
is that an application can pass and return remote object references as part of its normal
operation.
The first mechanism is based on establishing the naming service on the host machine.
RMI itself includes a simple service called RMI Registry. The RMI Registry runs on each
machine that hosts remote service objects and accepts queries for services, on port 1099 by
default.
By running the registry service, a server creates a remote service by instantiating the local
object that implements that service. This object is then exported to RMI. After exporting,
the server registers the object in RMI Registry under a public name. The public name of
the service is a simple string. When the object is exported, RMI creates a listening service
that waits for clients to connect and request the service.
From the client side, the RMI registry can be accessed through java.rmi.Naming or
java.rmi.registry.LocateRegistry static classes. Knowing the host address, port number and
name, the service can be located and a stub can be downloaded.
7
2.2
Communication with remote objects
After the reference to a remote object (stub) is retrieved, the communication looks like a
standard method invocation. Details of communication between remote objects are handled
by RMI.
After the invocation of a remote method, the stub:
1. initiates the connection with remote JVM containing remote objects,
2. marshals (writes and transmits) the parameters to the remote JVM,
3. waits for the result of the method invocation,
4. unmarshals (reads) the return value or exception returned, and
5. returns the value to the caller.
Server side:
1. unmarshals (reads) parameters for the remote method,
2. invokes the method on the actual remote object implementation, and
3. marshals (writes and transmits) the result (return value or exception) to the caller.
2.3
Loading class bytecodes for objects that are passed as parameters or return values
Figure 3: Client Server system
Because RMI allows a caller to pass any serializable objects to remote objects, RMI provides the necessary mechanisms for loading an object’s code as well as transmitting its data.
Serializable means that it implements the java.io.Serializable interface.
8
Figure 3 also shows that the RMI system uses an existing web server to load bytecodes
of classes written in the Java programming language, from server to client and from client
to server, for objects when needed. RMI can load class bytecodes using any URL protocol
(e.g., HTTP, FTP, file, etc.) that is supported by the Java platform.
2.4
Garbage collection of remote objects
Just as in normal applications, it is desirable to automatically delete objects that are no
longer referenced. In this way, the programmer does not need to keep track of remote objects
and their disposal. RMI uses reference-counting garbage collection algorithm.
Programmers need to be aware of some situations. It is possible that the object is discarded prematurely. For example, in a situation where the RMI believes that a client has
disconnected. In other words it is possible that a remote reference may, in fact not refer to
an existing object. When the user attempts to use such a reference, an exception is being
thrown and must be handled by the application.
More about the garbage collection mechanism of remote objects is covered further in the
document.
2.5
RMI communication through firewalls
Nowadays, the presence of network security technologies like firewalls is nothing unusual.
A typical firewall allows applications to communicate only on specific ports. This is one of
the reasons why distributed programming technologies like RMI are difficult to get to work
in practice. RMI transport layer normally attempts to open direct sockets to hosts on the
Internet but this attempt is interrupted by firewall.
One solution to this is tunneling. That means using a port that is very likely to be open.
Commonly, this will be the port 80. Therefore, the default RMI transport provides two
alternate HTTP-based mechanisms.
To bypass the firewall, the transport layer embeds an RMI call within the firewall-trusted
HTTP protocol. Firstly, the RMI call data is sent as the body of an HTTP POST request.
The return information is sent back in the body of the HTTP response. The transport layer
will formulate the POST request is one of the following two ways:
1. HTTP request is directed to an arbitrary port on the host machine. In the first
scenario, the firewall proxy will forward an HTTP request to this port. The default
RMI transport layer on the target machine uses a server socket to listen and decode
the RMI calls inside POST requests.
9
2. In the second scenario, the firewall proxy will only forward an HTTP request directed
to certain well-known HTTP ports. In this case the call is forwarded to the HTTP
server listening on port 80 of the host machine, and a CGI script is executed. The call
is then forwarded to the target RMI server port on the same machine.
2.6
Remote object activation
Distributed systems are designed to support long-lived persistent objects. Because these
systems will be made of thousands of objects it is unreasonable for these objects to stay
active all the time. It is inefficient to take up valuable system resources for indefinite period
of time.
Object activation is a mechanism for providing persistent references to objects. These
objects can begin execution on an as-needed basis. When a method is invoked on an activatable remote object and this object is not currently executing, the system initiates the
object’s execution.
Difference between active and passive objects:
1. An active object is a remote object that is instantiated and exported.
2. A passive object is one that is not yet instantiated (or exported), but which can be
brought into an active state.
Bringing a passive object to its active state is known as activation. In RMI, lazy system
activation is used. Lazy activation defers activating an object until a client’s first use.
Lazy activation is implemented using a faulting remote reference. Each faulting reference
consists of an activation identifier and transient remote reference. Activation identifier contains enough information for activation. The transient reference is the actual “live” reference
to the active remote object.
If the live reference to a remote object is null, the target is not known to be active. Upon
method activation the faulting reference engages in the activation protocol to obtain “live”
reference for newly activated object.
To be concrete, a remote object’s stub contains a faulting remote reference type that
contains both: an activation identifier and a “live” reference containing the “active” remote
reference.
10
2.7
2.7.1
Enhance Java RMI with security
Secure network connection with policies
A Java program may specify a security manager that determines its security policy. It is
done by passing an object of type SecurityManager to the setSecurityManager method of
the System class. Several techniques can be used to modify security policy of a program.
The simplest technique is to define a subclass of SecurityManager where “check” methods,
for which you want a different policy, should be overridden. This technique is obsolete now,
because it was hard not to leave any security holes. For this reason, a new technique was
introduced, which is backward compatible.
In recent RMI versions, “check” methods are now implemented by new checkPermission
method. This method checks whether the specified permission is implied by a list of granted
permissions.
This list is utilized in objects of new Policy class. An instance of Policy class handles
policy configuration file, which is read when the program starts and at any time a request is
made to refresh the security policy.
2.7.2
Encrypt network connection
The type of socket to use is an application-specific decision. If your server sends or receives
sensitive data, a socket that encrypts the data might be preferred. Is is used by implementing RMIClientSocketFactory and RMIServerSocketFactory interface and using them while
exporting new remote object.
2.7.3
Enable authentication
Dealing with authentication can be implemented by using additional RMI login service.
Also JAAS (Java Authentication and Authorization Service) can be used and this is the
preferred solution on server side.
2.7.4
Transactions
When a remote method is invoked, the control is passed to the server. Server can use a
transaction mechanism of choice, such as JTA (Java Transaction API).
JAAS and JTA are not a part of RMI so they will not be covered in this document.
11
2.8
RMI-IIOP
RMI over IIOP (RMI-IIOP), developed jointly by IBM and Sun, is a version or Java RMI for
IIOP (Internet Inter-ORB Protocol) that combines RMI’s easy programming features with
CORBA’s interoperability.
2.8.1
Before RMI-IIOP
Figure 4: Before RMI-IIOP
Figure 4 describes the situation of RMI and CORBA before the development of RMIIIOP. The space above the horizontal line represents the original domain of RMI; the lower
region represents the world of CORBA and IIOP. These two separate worlds, having been
developed independently, have not historically been capable of communicating with each
other.
2.8.2
After RMI-IIOP
Figure 5: After RMI-IIOP
Figure 5 describes the situation of RMI and CORBA after the development of RMIIIOP. The top section represents the RMI (JRMP) model, the middle section the RMI-IIOP
model, and the bottom section the CORBA model. An arrow represents a situation in which
a client can call a server. RMI-IIOP belongs in the IIOP world below the horizontal line and
supports both JRMP and IIOP protocols.
12
What is the meaning of the dotted line connecting the RMI-IIOP client with the CORBA
server? An RMI-IIOP client cannot necessarily access all existing CORBA objects. The
semantics of CORBA objects defined in IDL are a superset of those of RMI-IIOP objects,
which is why an existing CORBA object’s IDL cannot always be mapped into an RMI-IIOP
Java interface. It is only when a specific CORBA object’s semantics happen to correspond
with those of RMI-IIOP that an RMI-IIOP client can call a CORBA object. The dotted
arrow indicates a connection that is sometimes – but not always – possible.
2.8.3
Development procedure
For converting RMI (JRMP) code to RMI-IIOP, the programmer should be aware that there
are some implementation differences when running over IIOP:
ˆ Distributed garbage collection is not supported by CORBA, which uses explicit destruction and persistent object references with transparent passivation and activation
ˆ The RMI registry is replaced by JNDI with the CosNaming or LDAP service provider,
and RMI activation is replaced by the portable object adapter
ˆ Remote object references must be downcast using a programmatic narrow() method
instead of a direct Java language cast
Differences in server development
Because the usual base class of RMI-IIOP servers is PortableRemoteObject, the import statement must be changed accordingly as well as the derivation of the implementation class of
the remote object. Next, because the class used as the naming service has changed to InitialContext, the programmer must also change this import statement and use an InitialContext
to request naming registration of a remote object. After completing the Java coding, a tie for
IIOP must be generated, using rmic compiler with the -iiop option. Next, the CORBA CosNaming tnameserv must be executed as a name server instead of rmiregistry. For CORBA
clients, IDL must also be generated from the RMI Java interface, using the rmic compiler
with the -idl option.
Differences in client development
All the changes in the import statement for server development, discussed above, apply
here; in addition, a local object reference from the registered object name must be created.
The lookup() method returns an instance of java.lang.Object, and the narrow() method of
PortableRemoteObject must be used to convert it to its subtype. Stubs for IIOP are generated using the rmic compiler with the -iiop option.
13
3
Quality aspects addressed by the system
3.1
ISO/IEC 9126-1
This is the first part of the international standard for the evaluation of software quality.
This part classifies software quality in structured quality model. The model is a set of
characteristics and sub-characteristics.
The illustrations of all characteristics:
1. Functionality
2. Reliability
3. Usability
4. Efficiency
5. Maintainability
6. Portability
To find which quality aspects are addressed by the system, second look at the system is
needed. Each characteristic is then analyzed with respect to which parts of the system it
affects.
3.2
Efficiency
Efficiency aims to address how good the system performs and how the resources are used.
3.2.1
Performance
This is the first quality aspect that comes to mind. It is not hard to guess why good performance is that important. First thing that users observe is performance loss. Distributed
systems operate through various networks. That is the reason why majority of performance
issues come hand in hand with communication.
Parts of the system that affect performance:
1. Overall architecture of RMI. We trade this performance loss for the comfort of not
dealing with sockets and engaging in creating application-level protocols.
2. Communication through firewalls. Remote method protocols are already quite long.
Wrapping these calls in another HTTP header restricts performance even more. HTTP
connections last only for one transaction, e.g., method call. With this technique we
are creating and destroying socket connections repeatedly. These calls are at least an
order of magnitude slower that those sent through direct sockets.
14
3.2.2
Resource utilization
RMI tries to utilize resources as best as it can. Part of the system that is evidently designed
for RMI to better handle resources is Remote Object Activation. Distinction between active
and passive objects gives us the possibility to begin execution on an as-needed basis.
3.3
Functionality
Desired functionality for distributed systems is security. Therefore, security is the main
subcategory focused in this part.
3.3.1
Security
Distributed systems are connected to the Internet and our applications are exposed to the
outside world by default. It is for the user’s sake to protect the data and communication
from potential attacks.
As mentioned earlier, with help of regular Java and RMI, these new features can be added:
1. Secure network connection with policies. Setting up the SecurityManager is the basic
task here. In fact when the developer does not set up a SecurityManager, some functionality will be prohibited e.g. RMI’s class loader will not download any classes from
remote location.
2. Encrypt network connection. Creating new socket factories and using customized sockets with encryption for server and client side.
3. Enable authentication and transactions. Taking advantage of Java and adding Java
functionality throughout the system.
3.4
Maintainability
Maintainability represents effort needed to make specified modifications or the ease with
which a product can be maintained. Issues affecting maintainability are scattered around
the whole system. Because of this, the following lines are focused on what is affecting
maintainability of RMI.
Maintainability is positively affected by:
1. Advantages of Java as a programming language like memory management, platform
independence, simplicity, etc.
2. Distributed garbage collecting enhances memory management of simple Java applications. Developers are freed from this potentially hard memory management.
15
Maintainability is negatively affected by:
1. Architectural decision that every remote call can throw exception. Authors of RMI
had robustness of RMI applications in mind. RMI forces developers to take care of
every possible exception that can arise. Because of this, developers need to handle
additional source code.
2. RMI application can be very simple, but in many cases that is not enough. Additional
functionality is added to the core of the system like security, remote method activation
and others.
3.5
Usability
Usability express the effort needed for working with RMI and possible usages of RMI.
Regarding attractiveness and learnability as the most relevant usability subcharacteristics,
RMI API is clean and with no necessary overhead. The first distributed system can be easily
assembled in no time. Java RMI is available for free therefore very attractive. Documentation
is well done and gives quick glimpse at RMI architecture and functionality.
RMI is object oriented because it can pass full objects as arguments and return values. This
has great usability potential over traditional RPC systems. Passing objects gives developer
useful power of object oriented technology in distributed computing like usage of object
oriented design patterns.
16
4
4.1
Architectural View
Service registering
The important functionality provided by RMI is remote service registering using RMI Registry. At first, the remote object on the server machine is being registered in the RMI
Registry service using bind method of java.rmi.Naming class. When the operation returns
successfully, RMI client can use lookup method of the same class to find the registered service
by its name, and then, using the stub object returned, call the remote method on remote
object. The whole process can be seen on Figure 6.
Figure 6: Registering of RMI service using RMI Registry service
4.2
Client-server communication
The top level communication was designed to work in client-server architecture. Since all
network implementation details are hidden in Stub & Skeleton layers, user is left with a
simple API for the client side and can call the remote method on a Stub object directly.
Within the set of hidden layers (see Figure 7) the whole process of network communication
is being executed. To get through the network, Stub must serialize the method call data
(a substantial part of serialized data are method call parameters) and use low level Socket
methods to send (send()) and then receive (recv()) the answer. On the server side (Skeleton
layer), there is more Socket communication and object serialization before the actual remote
call to server object can be done. This is required to ensure the data correctness and to
maintain the high level method call interface of server object (server objects behave just like
any other high level classes and again, do not need to deal with network protocol details).
17
Figure 7: Remote object call in client-server RMI architecture
4.3
Distributed garbage collection
Garbage collection is a very useful feature of Java programming language. It increases
maintainability, making the application easier to code. However, it also means a loss of
performance, due to the overhead it represents.
18
Garbage Collector works well inside a single JVM. However, a problem with stubs arises
in a distributed system. The obvious way to solve this issue is to use distributed reference
counting. The client machine will first send a message to the server when the stub is instantiated to let it know that he is an active client. Then, it sends another message when
the stub is freed. The RMI runtime of the server, meanwhile, simply keeps track of the
number of active clients. When there are no active clients, the object will be reclaimed by
the Garbage Collector. This first simple approach has some inherent problems:
ˆ The client can crash. If the client crashes then the second message is never sent. The
server’s reference count never gets to 0, and the RMI runtime keeps the server object
active forever.
ˆ Network problems may arise. Even if the client is well-behaved and sends its message,
the network may be down. In which case, the RMI runtime never decrements the
server’s reference count to 0, and the server object is kept active forever.
These problems can be solved using Leasing. The basic algorithm works like this:
1. A client calls the server and requests a lease for a period of time
2. The server responds back, granting a lease for a period of time (not necessarily the
original amount of time)
3. During this period of time, the distributed reference count includes the client
4. When the lease expires, if the client has not requested an extension, the distributed
reference count is automatically decremented
As this whole process requires messages to be sent between the client and the server,
maintaining a data structure to store the object count on the server side, as well as applying
the basic garbage collector, it is obvious that the performance suffers. Still, the gain in terms
of maintainability (i.e., avoiding memory leaks and orphaned objects) makes this a positive
trade-off overall.
4.4
Java RMI with threads
In Java RMI, threads can be used at both the client and the server end of an interaction.
They represent a means to increase performance, but at the same time the maintainability
becomes harder, as additional code has to be written for synchronization issues.
In the case of servers, the main motivation is to increase the throughput of the server
and (hence) to enhance the scalability of the server (a crucial concern in modern distributed
systems). In the case of clients, the motivation is to prevent clients from being blocked while
an invocation is in progress. In particular, one thread can await the result of the RMI while
another can continue to do useful work. Alternatively one thread can generate data which
19
Figure 8: Distributed garbage collector mechanism
Figure 9: java.rmi.dgc interface
can then synchronize with a second thread that performs remote invocations.
The actual way to have threads in a Java RMI application is by using Java’s threading
capabilities, i.e. the java.lang.Thread class. The normal way of using this class is to create
a subclass of java.lang.Thread and then override the run() method (the code to be executed
by the thread. As with any concurrent programming, it is necessary to provide a level of
concurrency control. Java provides a number of primitives for this purpose. Crucially, Java
supports the synchronized keyword that enables the creation of monitors. A given class can
have a mixture of synchronized and non-synchronized methods, with the former preserving
monitor semantics on concurrent access, i.e. mutual exclusion. Java also offers condition
variables, with methods wait(), notify() and notifyAll(). Finally, the thread class itself has
methods for synchronization purposes such as join() and interrupt().
Server-side threads in Java RMI
One method of improving a server’s performance is to create a thread for each remote method
20
invocation, allowing multiple calls to be processed concurrently. Therefore, several clients
are not blocked in a queue waiting for their call to be executed. Java RMI automatically
provides you with this level of server-side threading; this policy is described as follows in
the RMI specification: “A method dispatched by the RMI runtime to a remote object implementation (a server) may or may not execute in a separate thread. Calls originating from
different clients Virtual Machines will execute in different threads. From the same client
machine it is not guaranteed that each method will run in a separate thread”. Therefore, if
you make remote calls from separate clients (executing in different JVMs) each call will run
in a separate thread. However, if you make concurrent calls from the same client (this can be
achieved by using client-side threading, see later) then it is possible these calls will execute
on the same server thread.
Figure 10: Java RMI Server-side threading example
Client-side threads in Java RMI
When a client makes a call in RMI, it blocks waiting for the result of the method invocation
to be returned. This is inefficient; if the client does not need the result urgently or there is
something else that needs to be processed then it can be performed while the call is blocking.
To implement this in RMI, you add threads to your client. That is, one thread is created
for the call (it calls the method and awaits the result) and other threads are created on the
client to perform alternative tasks (e.g., another remote call).
Consequences of the Java RMI threading policy
The Java RMI policy of providing threading automatically within the server is beneficial (it
saves you from writing the threading code). However, the ability to allow multiple methods
to run concurrently on a server is not thread safe. With such concurrent execution, it is
possible for client requests to conflict. For example, two clients could concurrently attempt
to write to the same field in a database (or any shared data structure on the server). This
may result in one of the writes being lost. Therefore, you must ensure that access to a shared
21
Figure 11: Java RMI Client-side threading example
data structure is controlled, so that concurrent client calls (running in separate threads) do
not conflict.
4.5
Remote exceptions handling
RMI is based on communication via network, which causes higher demands on the running
application stability and safety of the connection.
To make such application and method invocation stable and robust, new specialization of
java.io.IOException was made, called java.rmi.RemoteException, which implements the Serializable interface.
It is a common superclass for different exceptions related with communication, which may
occur during calling the remote method.
If an interface extends java.rmi.Remote, it must have RemoteException stated in its throws
clause, as can be seen in listing 1.
im po rt java . rmi . R em ot eE x ce pt io n ;
p u b l i c i n t e r f a c e R em ot eI n te rf ac e e x t e n d s Remote {
p u b l i c i n t g et Re mo t eM et ho d ( ) throws R em ot eE x ce pt io n ;
}
p u b l i c c l a s s R e m o t e I n t e r f a c e I m p l implements R em ot eI n te rf ac e {
@Override
p u b l i c i n t g et Re mo t eM et ho d ( ) throws R em ot eE x ce pt io n {
// s o u r c e code h e r e . . .
}
}
Listing 1: Remote method declaration
22
Figure 12: Remote Exception and Security Manager in RMI
Remote exceptions are much of a help for debugging the application, while adding a little
bit more overhead for programmer and influencing the runtime of the program.
Remote exception belong to checked exceptions, which, as was already mentioned, must
Java classes have declared in their signature and any method that calls method throwing a
checked exception must either catch it or be declared as throwing that exception.
Approach of throwing checked exceptions has its pros and cons. Safe application on one side,
unreadable code, unstable method signatures, exception swallowing or too much exception
wrapping on the other side.
4.6
Role of the JVM
Java code is executed in JVM, providing the ’Write Once, Run Anywhere (WORA)’
portability. To understand the role of JVM in the remote method invocation, it is necessary
to know something about its role in ordinary Java applications first. If a parameter to a
method in one, single JVM, is passed, the behavior of Java language is to pass it by value.
JVM makes a copy of that value, places it on the stack and then executes the method.
When the parameter is used inside such a method, its stack is accessed and the copy of the
parameter is used. Return values from methods are passed by value as well. Such behavior
can be observed for primitive types (e.g., boolean, int, float) but this is not the case for
objects as they reside in the heap memory and are accessible via references.
23
In this case, a copy of a reference (message) is made, placed on the stack, and the reference
count to java.lang.String is increased by one. In a method, copy of the reference variable is
used to access the object. One may think how RMI passes parameters and return values.
Primitive data type parameters to a remote method are passed-by-value parameters. RMI
creates a copy of such primitive and sends it to the remote method for execution. This is
also the case for returned primitives. These values, passed between JVMs are in machineindependent standard format (allowing virtual machines to run on different platforms).
When a object is passed as a parameter, the approach is different from one single JVM.
This time not the reference variable is passed by value, but the object itself. So if an object
is passed as a parameter or returned from the remote method, copy of the whole object is
sent. Object can be complex and may contain references to the other objects. All of them
are stored in the heap memory, which is not shared between JVMs, so not only the single
object will be copied, but the whole graph-like structure. This is a non-trivial task. To make
it more effective and not so demanding for CPU and network bandwidth, RMI technology
called Object Serialization is used (objects are transformed to a linear format) and then
sent via network. In the other JVM those objects are deserialized and prepared for the Java
program.
Figure 13: Client - server communication
Because of the redundant use of JIT compiler, performance is affected by the possibility
of sending objects as parameters or returning them as return values of method. Due to
additional byte-code operations made in JVMs, RMI is usually slower in comparison with
the competition.
24
To see the influence of JVM and the difference in performance between local and remote
procedure calls and between server running in JVM and the server using JIT compiler, see
the following tests (results taken from: [3]). Experiment was made with 10,000 invocations
of a local or remote method (sending and receiving different number of bytes). Local calls
were made with loopback interface.
If the function did not have parameters and no return value, elapsed time for 10,000
calls was 15.172 seconds for local call and 17.345 seconds for remote call. When sending
with parameter, local calls took 15.332 and remote calls 17.054 second. With return value
(and without parameter), local calls took 15.292 seconds and remote call 17.105 seconds.
When sending arrays with fixed length instead of bytes, the results are different. With array
parameter (size 1440 B) took the local calls 25.537 seconds and remote calls 34.209 seconds.
Without the parameter and with returning value, the difference was smaller, 27.099 for local
call and 33.408 seconds for remote call.
If the server runs with JIT compiler, local calls with loopback interface are significantly
faster, however the remote calls are not much influenced. The length of local calls in second is
12.377 without parameters or return values, 12.488 with parameter and 12.438 with return
value, both for byte passed by value. Remote calls took 17.976 with null, 17.735 with
parameter and 17.746 with return value. With byte array with fixed length were the local
calls faster, with 21.651 for call with parameters and 22.473 with return value, in comparison
with remote calls with lengths of 35.511 and 33.988 seconds.
4.7
Scenario view
The main purpose of using RMI is executing remote methods. Since those methods exist on
a server, the first step to achieve this purpose is to establish a connection with RMI server.
Figure 14 presents those actions as two main use cases. There are, however, numerous use
cases related to those mentioned. A few, that play a significant role dealing with security
and usability, two quality aspects considered essential for RMI, were distinguished and can
be seen in the diagram.
25
Figure 14: Chosen security and usability RMI use cases
5
5.1
Technical Aspects
Security manager
For checking the connection state and basic security, RMI provides a security manager, which
extends the standard Java security manager (java.lang.SecurityManager ), but does not add
any new functionality. The process of RMI security manager creation and a sample use are
shown in listing 2.
i f ( System . g e t S e c u r i t y M a n a g e r ( ) == n u l l ) {
System . s e t S e c u r i t y M a n a g e r ( new R M I S e c u r i t y M a n a g e r ( ) ) ;
}
p u b l i c c l a s s R M I S e c u r i t y M a n a g e r e x t e n d s java . lang . S ec ur it y Ma na ge r {
p u b l i c R M I S e c u r i t y M a n a g e r ( ) {}
}
26
S ec ur it y Ma na ge r sm = System . g e t S e c u r i t y M a n a g e r ( ) ;
sm . checkConnect ( ” r e m o t e h o s t ” , 1 0 9 9 ) ;
sm . c h e c k P r o p e r t y A c c e s s ( ” j a v a . rmi . s e r v e r . c o d e b a s e ” ) ;
sm . checkRead ( ” /tmp/ f i l e ” ) ;
sm . checkListen ( 1 0 9 9 ) ;
Listing 2: Sample use of Security Manager’s check methods
By default, there are no restrictions placed on remotely loaded objects in a RMI program
and no security manager is installed. This way it is possible to allow access of an insecure
code to your private data.
Instead of just creating the security manager, it is also possible to create your own security
manager implementations and enforce custom security policies, by defining the value of
java.security.policy property, as can be seen in listing 3.
java −Djava . security . policy=poli cyfilena me
Listing 3: Specifying a security policy file at runtime
Java looks for the policy files in directories, where JDK or JRE are installed, for a systemwide policy file as well as for user defined.
Example of policy file syntax and a policy file, which gives full access permissions to everyone
can be seen in listing 4.
grant {
permission java . security . AllPermission ;
};
Listing 4: Granting all permission to everyone
Security is essential (and very problematic) when concerning remote calls to other address
spaces. Weak security measures can make the protocol unusable due to malicious code and
no protection of private data, strong security measures make the communication too slow.
5.2
Handling sockets with socket factories
The wide presence of interfaces in RMI allows the user to replace many areas of functionality with custom user code. To achieve this, common design patterns are being used
throughout the implementation. For sockets management, a set of socket factories is provided, of which some allow the enablement of additional security mechanisms - such as Secure
Sockets Layer (SSL) encryption. What is more, custom user defined factories can be used by
RMI implementation, therefore, user might have a commit his influence to many significant
source areas, such as the one responsible for communication. Relationships between built-in
socket factories are presented in Figure 15.
27
Figure 15: Sockets factories and their SSL equivalents
The fact of other security mechanisms available does not obviously mean, that the default
implementation if flawed and not secured. Socket factories perform numerous checks on SecurityManager. This is a significant overhead, however, since the operation of establishing
connection is a security bottleneck and, as explained throughout the previous chapters, that
security is a major quality aspect of a system, which works on the network, we might conclude, that such architectural decision might be justified. A sample code snippet regarding
this matter in java.rmi.server.RMISocketFactory class can be examined on Listing 5.
p u b l i c s y n c h r o n i z e d s t a t i c v o i d s e t S o c k e t F a c t o ry ( R M I S o c k e t F a c t o ry fac )
throws IOException
{
i f ( factory != n u l l ) {
throw new S oc ke tE x ce pt io n ( ” f a c t o r y a l r e a d y d e f i n e d ” ) ;
}
S ec ur it y Ma na ge r security = System . g e t S e c u r i t y M a n a g e r ( ) ;
i f ( security != n u l l ) {
security . c he ck Se t Fa ct or y ( ) ;
}
factory = fac ;
}
p u b l i c s y n c h r o n i z e d s t a t i c v o i d s e t F a i l u r e H a n d l e r ( R M I F a i l u r e H a n d l e r fh )
{
S ec ur it y Ma na ge r security = System . g e t S e c u r i t y M a n a g e r ( ) ;
i f ( security != n u l l ) {
security . c he ck Se t Fa ct or y ( ) ;
}
handler = fh ;
}
Listing 5: Security aspects of java.rmi.server.RMISocketFactory
28
Figure 16: Remote objects inheritance model
5.3
Remote objects inheritance
An important aspect of RMI architecture is a deep inheritance approach. Many common
objects have multi-level hierarchy structures that are extensively used throughout the implementation. Figure 16 shows an example of such design for remote objects.
java.rmi.server.UnicastRemoteObject class is one of the most commonly used as a base
class for all remote objects on RMI server side. As usually with inheritance approach,
this is being done to save the user trouble of using external classes and instead to provide required functionality to objects that he created and is working with. This drastically
improves the usability of such objects, since, for instance, both learnability and understandability gain is substantial. On the other hand, the requirement to inherit a great amount
of code, that will not necessarily be used, is a clear disadvantage. Also the maintainability
suffers from this architectural decision as bigger class hierarchy is more difficult to modify,
not even saying that in case of errors, those are hard to analyze. As an excuse for this
maintainability loss is the fact of delegation of all lower level actions to implementation
classes (sun.rmi.server.UnicastServerRef and sun.rmi.server.UnicastServerRef2 in case of
Sun’s implementation). Listing 6. presents a piece of code, that gives an understanding of
this behavior.
p u b l i c s t a t i c RemoteStub exportObject ( Remote obj )
throws R em ot eE x ce pt i on
29
{
/*
* Use U n i c a s t S e r v e r R e f c o n s t r u c t o r p a s s i n g t h e b o o l e a n v a l u e t r u e
* t o i n d i c a t e t h a t o n l y a g e n e r a t e d s t u b c l a s s s h o u l d be used . A
* g e n e r a t e d s t u b c l a s s must be used i n s t e a d o f a dynamic proxy
* b e c a u s e t h e r e t u r n v a l u e o f t h i s method i s RemoteStub which a
* dynamic proxy c l a s s c an no t e x t e n d .
*/
r e t u r n ( RemoteStub ) exportObject ( obj , new U n i c a s t S e r v e rR e f ( t r u e ) ) ;
}
p u b l i c s t a t i c b o o l e a n unexp ortObje ct ( Remote obj , b o o l e a n force )
throws java . rmi . N o S u c h O b j e c t E x c e p t i o n
{
r e t u r n sun . rmi . transport . ObjectTable . unexp ortObje ct ( obj , force ) ;
}
/* *
* Exports the s p e c i f i e d o b j e c t using the s p e c i f i e d s e r v e r r e f .
*/
p r i v a t e s t a t i c Remote exportObject ( Remote obj , U n i c a s t S e r v e r R ef sref )
throws R em ot eE x ce pt i on
{
// i f o b j e x t e n d s UnicastRemoteObject , s e t i t s r e f .
i f ( obj i n s t a n c e o f U n i c a s t R e m o t e O b j e c t ) {
( ( U n i c a s t R e m o t e O b j e c t ) obj ) . ref = sref ;
}
r e t u r n sref . exportObject ( obj , n u l l , f a l s e ) ;
}
Listing 6: Functionality delegation behavior in java.rmi.server.UnicastRemoteObject class
30
6
6.1
6.1.1
Alternate Systems
RPC
General description
RPC (remote procedure call) is an Internet-process communication (exchange of data
among multiple threads in one or more processes) that allows a computer program to cause
a subroutine (piece of program that performs specific task and it is relatively independent of
the remaining code) or procedure to execute in another address space (in most of the cases
another computer on the network).
Aim is to do it without explicit coding for the remote interaction (sockets, getting through
the firewall, establishing the connection). If the software is object-oriented, RPC is called
remote method invocation.
The idea itself was first described in RFC 707 and then first used 5 years later, in 1981.
Since that time, a lot of new, evolutionary improvements have been done, such as NCS2, or
lately CORBA. They usually improve the functionality or make things easier to use. Every
such system has some underlying assumptions concerning their operating environment, using
many different (and often incompatible) technologies to accomplish this.
In RPC line, systems were built on assumptions of heterogeneity - assumption, that the
distributed system contains machines that might be different, running different operating
systems with different versions. To make the communication between such machines possible,
machine-neutral interface-definition language (IDL) descriptions are used.
6.1.2
Architecture
RPC needs to solve the problem of heterogeneity on the first place. As the solutions,
proxies were introduced on each machine that could send, receive and process messages from
different systems in a known by each other format. Analogously to RMI, the client proxy,
on which the client calls remote procedure is usually called stub while the proxy on the
receiving server - a skeleton.
First, client calls the stub (a local procedure call) (line 1 in the picture). Then the stub
packs the parameters into a message (line 2) which is then sent via the network (line 3).
This packing of parameters is called marshalling.
Message is sent by kernel from the client machine to the server, which are passed to the
server skeleton (line 4).
31
Stub then calls the server procedure and replies the other way around. Unpacking of the
parameters is called unmarshalling (line 5).
Figure 17: Remote procedure call model
6.1.3
Comparison with RMI
RMI is the Java version of what is generally known as a RPC, but with the ability to
pass one or more objects along with the request - object containing information that can
change the service in the remote address space. RMI is centered on Java language, while
RPC is multi-language (it has over 40 implementations including Java, Python, Ruby, PHP
and ASP) and is widely used for example in windows.
RPC is based on assumption of heterogeneity of address spaces, while RMI expects homogeneity (Java virtual machine should be installed on each remote computer) or in other
word, homogeneous collection of virtual machines. And even one step further, RMI expects
all objects to be written in Java.
Basically, both RPC and RMI are used for remote invocation of procedures/methods from
different address spaces, but with some important differences. RPC as a predecessor is not
necessarily object oriented; its static nature is perhaps the biggest disadvantage (information
passed over the network cannot use the advantages of polymorphism). The transmitted
object’s type cannot be a subtype of the type expected by skeleton. If a subtype is sent, the
system converts it to a reference of the exact type that the skeleton expects.
6.1.4
Usability vs. maintainability & performance
While RPC is multi-language and low level, it can get far too complex which weakens the
maintainability quality.
32
Object oriented approach has its own, well know advantages and disadvantages as well
as use of the Java programming language in RMI, with connectivity to existing system
using native methods, adding Java functionality throughout the system. RPC systems are
language neutral, which means RPC cannot provide functionality that is not available on all
possible target platforms (and are using a lot more overhead as well).
6.1.5
Performance comparison
The performance loss of using RPC versus a local procedure call is a factor of 10 (although
it is not the aim of RPC to replace local calls) and the performance is further influenced by
the way the server responds to many concurrent calls - so it depends on the language and
system used for implementing it.
Due to additional byte-code interpretation made in JVMs, RMI is slower than RPC (even
with the use of JIT compiler). The advantage RMI has is at multiple-concurrent method
invocation, thanks to multi-thread support in the language. But RMI provides NAT-firewall
traversal capabilities, asynchronous ARMI, easier use of CORBA, RDMI with dynamic invocation.
Figure 18: Response times for invocations returning smaller lists
Referring to the exhibit figure (results taken from [4]), several conclusion about speed
of different protocols while returning lists can be made. The test consisted from remote
invocations of a single method, which demands an integer parameter and return a specificsized list. Objects in that list contained different types (strings, long, integer, double, float)
and they were static.
33
With small lists, Java RMI was one of the fastest protocols, slightly losing its speed with
larger lists. In both cases, RPC protocols had the biggest response times.
6.1.6
Security issues
Security policy in RPC is done by server, which chooses the security provider and must decide
on which mechanism of authentication to use. In addition, there are some other technologies,
like IIS (for advanced authentication), SSL encryption and RPC proxy verification (working
mutually) or even choosing which machines are allowed to receive RPC on server network
(when calling via HTTP).
Then there is SSPI (secur32.dll), which provides a security interface for RPC, security
context provided by Windows Server 2003 Service Pack 1 (SP1) - for connection-oriented
connections (for instance Transmission Control Protocol - TCP). In short, it allows negotiation of multiple security contexts over one single connection.
RMI uses inherent capabilities of Java language and built-in libraries of it: use of security manager - for policy configuration, asserting the connections. Then using JAAS (Java
Authentication and Authorization Service) for additional RMI login services. It is not depending on the underlying systems. RMI provides a socket factory, able to create sockets of
any necessary type. This allows the use a protocol that is different than TCP/IP in transport
layer - provided by the default use of java.net.Socket.
However, RMI still needs to find the way how to implement real server-level security.
Security is a problem for RPC as well, although it is an older and more mature method
(sasser, blaster and other vulnerability exploits).
6.1.7
Summary
RPC became too complex for middleware use after all, however, it sill can serve as a low level
platform for more powerful middleware layers like RMI, that have powerful failure detections,
balanced loading and use object oriented approach. On the other hand, the latest versions
of RMI are becoming CORBA compatible and this system is and will probably be more
popular and widely used.
6.2
6.2.1
CORBA
General description
The Common Object Request Broker Architecture (or CORBA) is an industry standard
developed by the Object Management Group (OMG) to aid in distributed objects programming. It is important to note that CORBA is simply a specification. A CORBA implementation is known as an ORB (or Object Request Broker). There are several CORBA
34
implementations available on the market such as VisiBroker, ORBIX, and others.
CORBA was designed to be platform and language independent. Therefore, CORBA objects can run on any platform, located anywhere on the network, and can be written in any
language that has Interface Definition Language (IDL) mappings.
6.2.2
Architecture
CORBA defines an architecture for distributed objects. The basic CORBA paradigm is that
of a request for services of a distributed object. The services that an object provides are
given by its interface. Interfaces are defined in OMG’s Interface Definition Language (IDL).
Distributed objects are identified by object references, which are typed by IDL interfaces.
Figure 19 graphically depicts a request. A client holds an object reference to a distributed
object. The object reference is typed by an interface. In the figure below the object reference
is typed by the SWA interface. The Object Request Broker, or ORB, delivers the request to
the object and returns any results to the client. In the figure, a writeProject request returns
an object reference typed by the PDF interface.
Figure 19: CORBA Request
The ORB is the distributed service that implements the request to the remote object.
It locates the remote object on the network, communicates the request to the object, waits
for the results and when available communicates those results back to the client. The ORB
implements location transparency. Exactly the same request mechanism is used by the client
and the CORBA object regardless of where the object is located.
6.2.3
Architectural trade-offs of CORBA & Java RMI
Usability vs. Portability
While both CORBA and Java RMI are portable across multiple platforms, CORBA offers
a better portability as its services can be written in many different languages while RMI
supports only Java. However, to support multiple programming languages, CORBA relies
on IDL, interface description language, which must be learned. From this point of view, RMI
has a better usability, as its interfaces are written in Java, and no additional language must
be mastered. As CORBA is language-independent, it is ideally suited to use with legacy
systems (written in C++, Ada, Fortran, Cobol or others) and to ensure that applications
written now will be accessible in the future.
35
Security vs. Functionality
Java RMI has an improved functionality as it can introduce new code to foreign JVMs. On
the other hand, this makes security worse, as security threats with remote code execution
may appear. CORBA supports only primitive data types and a wide range of data structures
as parameters, but it does not support the transfer of objects or code.
Portability vs. Maintainability
Another consequence of being language-independent is that CORBA does not have a garbage
collector. Once a CORBA object is created, it continues to exist until the programmer gets
rid of it, and deciding when to get rid of an object is not a trivial task. Java RMI uses a
Distributed Garbage Collector (DGC), which has been earlier described in this document.
6.2.4
Performance
Performance is a delicate subject when it comes to comparing Java RMI to CORBA. It
depends on multiple factors like: the specific implementation of CORBA, the type of data
used in the tests (simple data, arrays, complex structures), the application’s type, the number
of clients accessing the server, and many more. Therefor it is really difficult to say which
one has better performance. However, using existing studies we can draw some conclusions.
Figures 20 and 21 best describe where Java RMI or CORBA (Visibroker implementation)
perform better[10].
Figure 20: Actual speed RMI vs CORBA: basic data types
For basic data types, Java RMI had the edge over CORBA for up to 4 clients. After
that CORBA was faster. This is explained by the threading policies of the two middleware
solutions. Java RMI uses the thread-per-request threading policy, which adds significant
36
Figure 21: RMI string vs CORBA string
overhead with the larger number of clients as each thread has to be created with the incoming request. The CORBA architecture, on the other hand, implements the worker thread
pooling policy, where a pre-specified number of threads is already created, each incoming
request being assigned to one of the available threads in the pool.
For large amount of data, the second image shows the performance of Java RMI strings
vs CORBA string. With the increasing string size and larger number of clients CORBA is
significantly faster than Java RMI.
6.2.5
Summary
Comparing RMI and CORBA does not reveal an optimum solution - one is not “better” than
the other. The properties of these two technologies lend themselves to different situations.
A comparison of RMI and CORBA helps to highlight individual strengths and weaknesses,
but the applicability of one technology over the other depends largely on the purposes for
which it is to be used, the experience of the developers who will design, implement and
maintain the distributed system, and whether non-Java systems are intended to access the
system now or in the future.
CORBA is suitable for large scale fully or partially web-enabled applications where legacy
support is required and good performances under heavy client load are expected. Java RMI
on the other hand is suitable for small scale fully web-enabled application where legacy support is not needed, where ease of learning and ease of use is more critical than performances
are.
37
7
Q&A
Hans Peerman: How does the RMI client contact the RMI server?
Answered in RMI Overview - Localization of remote objects.
Kevin van Ingen: It appears to me that RMI does not offer options to control
how threading is done. How can get control over threads?
Answered in the second presentation slide number 30.
A method dispatched by the RMI runtime to a remote object implementation (a server)
may or may not execute in a separate thread. Calls originating from different clients
Virtual Machines will execute in different threads. From the same client machine it is
not guaranteed that each method will run in a separate thread.
More about how to implement threads is in sections Java RMI with threads in this
document.
Maria Hernandez: Can every object be passed as an argument of a remote
method? or are there any restrictions with the type of the object? if it can,
must the class fulfill any condition?
Every Java object can be an argument, or a return value. Even objects that has never
been encountered by remote virtual machine. Only one condition must be fulfiled is that the
object is serializable. Serializable means that it implements the java.io.Serializable interface.
Alejandro Serrano Mena: If parameters are always passes by value (different
from the normal Java rule), how does RMI behaves when changes are done to
a object passed as parameter? Is it converted to a remote object? Even more,
can we break something with this change of behaviour, such as algorithms that
make use of object state?
Parameters are not always passed by value. Primitive types are passed in the same way
in local and remote calls, passing objects is different. Not the reference variable is passed by
value, but a copy of the whole object is sent through the network. More detailed explanation
can be found in chapter “Role of the JVM”.
Renato Hijlaard: How easy is it to extend an RMI application to RMI-IIOP
for communication with non Java code?
In order to convert a RMI application to RMI-IIOP (RMI over IIOP), changes have to
be done at both the client’s and the server’s implementation. The actual things to do are
described in this paper in Chapter 2, “RMI-IIOP”, “Development procedure”.
Tim de Boer: After I read the article, it’s clear how RMI handles connections
and how it can be used to setup a client-server situation. Although it’s pretty
nice, I can’t see the real appreciation of RMI in contrast to the more conventional
38
(none open-source) client-server products. In what sense does RMI differ from
other products (what makes RMI better or different then other products)? And
how (for what purpose) will RMI be mainly used in the future?
Java RMI’s main advantage over it’s competitors is the fact that it only relies on Java
as a programming language, which is well known and easy to understand for developers.
This makes RMI a product with a higher usability while still being portable across multiple
platforms (and even compatible with some legacy systems using RMI-IIOP).
Regarding RMI’s future, as RMI moves more toward IIOP and CORBA, and CORBA
extends its own functionality to incorporate the most desirable traits of RMI, the two technologies will continue to merge into a single, seamless, distributed object architecture that
takes advantage of both RMI’s and CORBA’s major strengths. So, in one form or another,
RMI will continue to be a valuable tool for Java programmers creating distributed object
environments.
Lambert Veerman: Because of Java’s design, an automated garbage collector is
needed, as manual dislocating objects is not supported as far as I know. Therefor
the distributed garbage collector is used, probably working by keeping count of
the references to an object. Suppose your server’s memory is filled with objects
referenced from remote servers. How does the distributed garbage collector
handles exceptions like a failing connection, e.g. an object is set null but the
return call to your server never made it, the connection is dropped or a crashed
client program.
Indeed, for each object, a count is stored. However, to address the issue of failing connections the Distributed Garbage Collector uses a Lease mechanism, in which the client uses
the object for an amount of time, after which, unless he extends his lease, the object’s count
will decrease. This way, in case of a disconnected client, when it’s lease expires, the object’s
count will not remain stuck, and eventually the object will be garbaged collected. More
details about how this works is presented in Chapter 4, “Distributed garbage collection”.
Robert Vroon: Java RMI is Java based and can only call other Java applications. CORBA, on the other hand, is language independent. Will Java RMI
also be language independent in the future or is that not the intention of Java
RMI?
Java RMI can only call other Java applications natively, but by using RMI over IIOP it
can also support other languages.
Thijs Alkemade: It might be hard to predict how big objects can become in a
Java application. Is it possible to compress objects before sending them?
Because of the possibility of sending really complex graph-like structures of objects via
network, which is really non-trivial task, RMI uses serialization. However, it is an mechanism
built into Java libraries for writing a graph of objects into a stream of data. This stream
39
can be then manipulated by programmer. To compress the size of such stream, several
possibilities are possible. You can use Custom Socket Factories to add compression, Java is
even supporting zipping (not only ZipInputStream and ZipOutputStream).
Sander van der Rijnst: Compared to TCP/IP socket connections, what are the
pros and cons of using RMI over TCIP/IP?
First of all, comparing RMI and TCP/IP socketing just like that is a simplification. The
main difference would be the marshalling of data, because RMI takes care about that. RMI
can use RMISecurityManager class to verify user identity and give him the different level of
access to remote objects depending on that. However SSL layer has similar functionality.
RMI can make server requests on demand (by extending Activable class).
Matthias Lossek: For remote methods with the return type void, is there any
guarantee that a remote call has been processed or is the call lost when the
connection breaks down? If there is a guarantee, how does it work?
In the RMI documentation is stated this note: The RMI system preserves ”at most once”
semantics for remote calls. In other words, a call to an activatable or unicast remote object
is sent at most once. Thus, if a call to a remote object fails (indicated by a RemoteException
being thrown), the client can be guaranteed that the remote method executed no more than
once (and perhaps not at all).
If something unexpected happed you always know it because RemoteException is thrown.
From the note above it can be understood that method could be executed or not. It will be
up to the developer to check the state of object after such unexpected situations.
Theodoros Polychniatis: What are the most interesting technologies that make
the use of RMI easier? (like EJB, Spring...)
First of all, RMI is technology on its own, application programming interface that can be
used along with EJB for instance. Then the answer for the question and better undestanding
of the problem can be found at [2].
Jeroen van der Velden: How is it possible to set different kind of permission
levels between clients using the RMISecurityManager?
Mark Rouhof: “Safe and Secure: RMI uses built-in Java security mechanisms
that allow your system to be safe when users downloading implementations.
RMI uses the security manager defined to protect systems from hostile applets
to protect your systems and network from potentially hostile downloaded code.
In severe cases, a server can refuse to download any implementations at all.”
How does this build-in Java security mechanisms look like?
The security scheme is based on policies and permissions. Specific permissions are granted
to specific code based on the source of the code, the signer of the code, or both. When the
40
code from a client is loaded, it is granted permissions based on the security policy then in
effect.
The security policy files have a specific description language which allows the usage of
permission types: AllPermisions, FilePermision, SecurityPermission, etc. The policy files
can be edited in any text file, or the policytool utility can be used for a graphical interface
that eliminates the need for knowing the syntax.
To include your own policy file the following command is used: java -Djava.security.manager
-Djava.security.policy=yourURL yourApp.
Ruben van Vliet: Can you explain which security measures are taken to ensure
a safe communication between the client and the server? Are there ways to
improve this and does this have influence on the currently used architecture?
Communication isn’t secured by default. Part of the document mentioned enryption of
the communication. Is is used by implementing RMIClientSocketFactory and RMIServerSocketFactory interface and using them while exporting new remote object.This doesn’t
affectarchitecure in any negative way because this functionality is here for this purpose.
More about how to use custom socket factory can be seen here: [14].
Stijn van Drongelen: Does RMI support fine-grained (per class, per object,
per method) authorization? Is this just a server implementation matter, or does
it need specific support in the data model and/or the network protocol?
RMI proxy can be used for that. “These new concepts of permission and policy enable
the JDK to offer fine-grain, highly configurable, flexible, and extensible access control. Such
access control can now not only be specified for applets, but also for all Java code, including
applications, beans, and servlets.” according to SUN, taken from [13].
Nikos Mytilinos: In the paper you have suggested we can read that “Java
embraces the ’Write Once, Run Anywhere’ model. RMI extends the Java model
to be run everywhere.” Nevertheless, RMI was designed for a single language
where all objects are written in Java. I think it is interesting to include in your
architecture document how the interoperability between different platforms can
be implemented and provide some examples to show differences in performance
(if any) in comparison with native Java implementations.
The interoperability between different platforms can be achieved by using RMI over
IIOP. Regarding performance, tests have shown that even if RMI-IIOP uses the standard
IIOP protocol for which it has to make additional transformations and mappings, the careful
design and implementation of the model, together with careful performance analysis and
implementation of several optimizations, have enabled comparable and in some cases even
superior performance [9].
Rik Janssen: In the document you have sent the author writes the following.
“The RMI system is designed to provide a direct, simple foundation for dis41
tributed object oriented computing. The architecture is designed to allow for
future expansion of server and reference types so that RMI can add features in
a coherent way.” The assignment we have to make, is that of making a ’blue
print’ of the architecture of a particular system. In your case RMI, but what do
you think of the statement that it is not possible to make a architecture of programming language. In my opinion a programming language is building block to
make a IT system that is made using an architecture. The architecture of a programming language is the paradigm that is behind that particular programming
language. More information about this thought here. I would say that usage of
the term architecture in the above quoted text is not correct and should have
been replaced for ’The paradigm behind RMI allows for future..etc.’. How do
you think about my opinion and could you give some paradigms that are behind
JAVA RMI and do you think that the ’ideal document architecture’ described
on the SWA website, is suitable to the describe the RMI ’architecture’ ?.
Well, it is not a programming language in question here. RMI is a Java application
programming interface for remote procedure calls, middleware very well suited for architectural blueprints and to the ideal document described in the manual page. The thought
behind RMI is calling remote methods while using Java as the only programming language
and allow sending objects through the network. Anyway, your idea with paradigms behind
programming languages may be right.
Kevin van Blokland: I see Java Remote Method Invocation as a way of synchronizing classes. Several protocols are used to determine when data is out of
sync, when connections are lost etc. All of these protocols are build on the fact
that client x sends client y information about object z (a remote object). now
client y needs to update/retrieve/do anything with object z. Therefore z needs
to be looked up, state needs to be computed and so on. The interesting part to
me is how this lookup procedure is implemented. For instance, when we setup
a large Java server. This server publishing a lot of remote objects. Therefore
a lot of administration needs to be updated whether some objects are still in
memory, connections are lost... My question is how does the Jave middle layer
handles the object lookup of object z?
I think you described what is one of the basic functionality of RMI. Look at the Architectural View and Service registering in this document.
Leupolz, J.S.: To connect different business standard software in many cases
an Enterprise Service Bus is used. How does Java RMI get along with ESBtechnology and Application servers like JBoss?
Java RMI and JBoss comparison and benchmarks can be found at [8]. We have not found
any issues between RMI and ESB-technology so far.
42
Geert Wirken: Based on the documentation about Java RMI, and in particular
the ’Safety and Security’ section, I see that is possible to encrypt the connection using the SocketFactory. This class allows for instance SSL connections.
However, this only encrypts the data connection. Does Java RMI (or related
technologies) include features for authentication? I.e., can it verify whether a
certain client is allowed to execute methods on the remote server?
Java includes technology for authentication and authorization and it can be incorporated
in Java RMI. JAAS (Java Authentication and Authorization Service)
Sjors Otten: In the provided paper it was written that the server can enforce
a certain policy to its clients, which is a good thing. But how can I update my
policy and how easy is it do so? To what extent can a policy be constructed? Are
there limitations or can it be of unlimited number of codelines? Is it possible
to schedule the enforcement of an updated policy (i.e. version 1.1 should be
enforced from 15-12-2010 till 31-12-2010)? Can you choose to enforce a certain
policy on a specific client or application via the server?
The answers will be given to the questions separately. ’Is it possible to schedule the
enforcement of an updated policy (i.e. version 1.1 should be enforced from 15-12-2010
till 31-12-2010)?’ No it is not by default but one can implement a user specific script or
programs to deal with this issue. ’Can you choose to enforce a certain policy on a specific
client or application via the server?’ Can be implemented in a server logic, to upload policy
restrictions to the client. ’Are there limitations or can it be of unlimited number of codelines?’
This is not an RMI issue, this is an operating system issue, on what is the maximum size
of a text file. ’But how can I update my policy and how easy is it do so?’ You should use
a text editor preferably, there is however a possibility to edit that file in a binary form as
it is with any file, but this is not a recommended solution. The basic knowledge of editing
text files is required. However, if such ability is not held by the user, he might not be able
to work with RMI at all.
Alessandro Vermeulen: How can authentication be handled securely with for
instance certificates, without losing a lot of performance. Can a connection be
kept-alive so that multiple calls can go over the same connection? And how is
threading done? And in case you don’t want to wait on the response from the
‘server’ but you want a more event-driven model, do you have to program this
yourself with Queues or could this be (automatically) handled for you?
Java can support certificates but they are not part of RMI. After extending your application with certificates you need to expects some trade-offs. In Java RMI socket connections
can be used for multiple, successive transactions (method calls). You can see how is the
threading done in section: Java RMI with threads. You can use queue-like implementations
provided by Java language to deal with the issue of not waiting for the response. However,
in most cases, a standard multi-threading implementation is enough.
43
References
[1] Simon Nash Akira Andoh. RMI over IIOP. 1999. url: http://www.javaworld.com/
jw-12-1999/jw-12-iiop.html?page=1.
[2] EJB and RMI: A Practical Introduction. url: http://www.devx.com/Java/Article/
20843/0/.
[3] Lynn Zhang Sudha Krishnamurthy Geetanjali Sampemane Luis Rivera. HP-RMI :
High Performance Java RMI over FM. 2008. url: http://www- csag.ucsd.edu/
individual/achien/cs491-f97/projects/hprmi.html.
[4] Daniel Gredler. Java Remoting: Protocol Benchmarks. 1997. url: http://daniel.
gredler.net/2008/01/07/java-remoting-protocol-benchmarks/.
[5] William Grosso. Java RMI. 2002. url: http://books.google.ro/books?id=d9fvFC4
9TxcC&lpg=PR1&pg=PR4#v=onepage&q&f=false.
[6] ISO/IEC 9126. url: http://en.wikipedia.org/wiki/ISO/IEC_9126.
[7] Java RMI & CORBA A comparison of two competing technologies. url: http://www.
javacoffeebreak.com/articles/rmi_corba/index.html.
[8] JBoss Remoting Performance Benchmark Report. url: http://docs.jboss.org/
jbossremoting/docs/benchmark/performance_benchmark.html.
[9] Ivan Rozman Matjaz B. Juric. RMI, RMI-IIOP and IDL Performance Comparison.
url: http://lisa.uni-mb.si/~juric/jr3.pdf.
[10] Marjan Hericko Matjaz B. Juric Ivan Rozman. Performance Comparison of CORBA
and RMI. url: http://lisa.uni-mb.si/~juric/perfcompcrmi.pdf.
[11] ORACLE. Java Remote Method Invocation - Distributed Computing for Java. url:
http://www.oracle.com/technetwork/java/javase/tech/index- jsp- 138781.
html.
[12] ORACLE. Java Remote Method Invocation(Java RMI). url: http : / / download .
oracle.com/javase/6/docs/technotes/guides/rmi/index.html.
[13] Security, Overview of Security in JDK 1.2. url: http://www.dickbaldwin.com/
java/Java702.htm.
[14] Using a Custom RMI Socket Factory. url: http://download.oracle.com/javase/
1.4.2/docs/guide/rmi/socketfactory/index.html.
[15] Van Belle Werner. Automatic Generation of an Intelligent Concurrency Adaptor in
order to Mediate the Differences between Conflicting Concurrency Interfaces. 2004.
url: http://werner.yellowcouch.org/phd03/PhdOnTheWeb/node21.html.
44