RMI applications typically consist of two separate programs, a server-side program, and a client program. A typical server-side program creates some remote objects so that references to these remote objects can be accessed, waiting for the client to invoke the methods provided by these remote objects. A typical client program obtains a remote reference, points to one or more remote objects on the server, and then invokes the methods provided by these remote objects. Typically we call this a distributed object application.
How the 3.1 RMI works
What the Distributed object application needs to do:
L Find (locate) remote objects. Applications can use a variety of different mechanisms to obtain references to remote objects. For example, the application can be registered by RMI through the simple naming tool provided by RMI. Or the application can pass and return remote objects as part of a remote method call.
L communicates with remote objects. The details of communication between remote objects are handled by RMI, and for programmers there is no difference between the communication of a remote object and the usual Java method invocation.
L load the class definition of the remote object passed over. Because RMI allows objects to be passed in both directions, it provides a mechanism for loading object class definitions and passing object data.
(Figure 3.1) describes an RMI distributed application that uses the RMI registration mechanism to obtain remote object references. The server invokes the registration mechanism to associate a name with a remote object (or called a binding). The Client looks for a remote object based on its name in the registry mechanism of the server, obtains a reference to the remote object, and invokes the method of the remote object. The RMI system uses Web server, from server to client, or from client to Server, to load the class definition of the desired object.
3.1.1 Dynamic class Loading
A unique core advantage of RMI is the ability to load a class that is not defined in a Java Virtual machine (JVM) that is not on the receiving end. All types and behaviors of an object defined in a Java Virtual machine can be passed from this Java virtual machine to another Java virtual machine, even to a remote Java virtual machine. RMI passes objects based on the true type of the object, so the behavior of the object does not change when the object is passed to another Java virtual machine. This feature enables new object types and behaviors to be introduced into a remote Java Virtual machine, which means that the behavior of the application is dynamically extended. The Compute engine example below uses this ability to introduce new behavior into a distributed program.
3.1.2 Remote Objects
Like many other Java applications, a distributed application built on RMI is made up of interfaces and classes. Interfaces declare methods, classes implement methods defined in interfaces, and may also declare additional methods. In distributed applications, some methods may exist in some Java virtual machines but are not in another Java virtual machine. If a method of an object can be called between different Java virtual machines, this object is called a remote object (objects).
A common object can be transformed into a remote object by implementing the Remote Interface (Java.rmi.Remote), which has the following characteristics.
L A remote interface extension Java.rmi.Remote interface
The method declared in each remote interface declares the throw java.rmi.RemoteException exception, in addition to declaring that it is throwing itself to apply a specific exception
RMI treats remote and non-remote objects differently when an object is passed from one Java virtual machine to another. When RMI passes a remote object to another JVM, it actually passes the stub object corresponding to the remote object, rather than passing a copy of the object. This stub object acts as the delegate or proxy for the remote object, providing the client with a reference to the remote object. The client invokes the method of the obtained stub, which is responsible for executing the invocation of this method in the remote object.
A stub (stub) of a remote object implements the same collection of methods as the remote interface implemented by the remote object. This feature allows stubs to be transformed into remote interfaces implemented by remote objects. However, only those methods declared in the remote interface can be invoked by the JVM on the receiving side.
When a client makes a remote method call, the RMI framework translates the network communication failures encountered into RemoteException, and the client can catch the exception and handle it accordingly.
3.1.3 Parameters and return values in a remote method
The RMI specification provides the following provisions for the transfer of parameters and return values:
L only basic data types, remote objects, and serializable objects can be passed as parameters or return values.
L if the parameter or return value is a remote object, pass its stub object to the receiver. That is, the receiver gets the stub object of the remote object.
If the parameter or return value is a serializable object, the serialized data of the object is passed directly. In other words, the receiver gets a copy of the sender's serializable object.
If the parameter or return value is the base data type, the serialized data of the data is passed directly. In other words, the receiver gets a copy of the sender's basic data type.
3.1.4 the Equals (), Hashcode (), and Clone () methods of the remote object
The Equals (), Hashcode (), and Clone () methods are defined in object objects, and these methods do not declare throwing remoteexception. The Java language specifies that when a subclass overrides a parent class method, the subclass method cannot declare an exception that throws more than the parent class method. The RMI specification requires that methods in the remote interface must declare the remoteexception exception to be thrown, so the Equals (), Hashcode (), and Clone () methods cannot be defined in the remote interface. This means that these methods of a remote object can always be called only as local methods, by other objects within the local Java Virtual machine, and not remotely by the client as a remote method.
3.1.5 Distributed garbage Collection
In a Java virtual machine, for a local object, as long as it is not referenced by any variable in the local Java virtual machine, it ends the lifecycle and can be reclaimed by the garbage collector. In contrast to a remote object, it is also referenced remotely by a variable reference in the local Java virtual machine. If you register a remote object with the Rmiregistry registry, the Rmiregistry registry holds its remote reference.
The RMI framework uses a distributed garbage collection mechanism (dgc,distributed garbage Collection) to manage the life cycle of remote objects. The main rule of DGC is that this remote object will end the life cycle only if a remote object is not subject to any local references and remote references.
When the client obtains a server-side remote object stub, it sends a lease notification to the server telling the server to hold the reference to the remote object itself. This lease has a lease term that can be set by System attribute Java.rmi.dgc.leaseValue, in milliseconds, with a default value of 600 000 milliseconds. When the lease term is reached for half the time, the client will again send a lease notification to the server if it also holds a remote reference. If the server side does not continue to receive a new lease notification from the client after the lease expires, the server will assume that the customer is no longer holding a reference to the remote object.
Sometimes, a remote object wants to perform some action when it is no longer under any remote reference, such as freeing up resources for a secure end-of-life cycle. Such a remote object needs to implement the Java.rmi.server.Unreferenced interface, which has a unreferenced () method, in which the remote object can perform operations that release the associated resources that are consumed. The unreferenced () method of this object is called when the RMI framework detects that a remote object is no longer subject to any remote references.
3.2 Creating distributed Applications with RMI
Developing a distributed application by using RMI follows these steps: [3]
Designing components to implement distributed applications
Compiling source code
Make your class accessible on the network
Start the application
3.2.1 Design Implements application components
The architecture of the application is determined first, including which component is the local object and which component is remotely accessible. This step includes:
L define the remote interface. A remote interface specifies which methods can be called remotely by the client. The client program is programmed for the remote interface and not for classes that implement these remote interfaces. These interfaces are designed to include the object type that declares the parameters required by the remote method, and the remote method return value type.
l Implement remote objects. The remote object needs to implement at least one remote interface. Remote objects can also implement other interfaces, but the methods declared in this interface are available only on the local JVM. These classes also need to be implemented if any local class is to be used as a parameter to these (remote) methods or as a return value.
L Implement the client. After the remote interface is defined, the client using the remote object can be implemented at any time, at any time, after the remote object is deployed.
3.2.1.1 Implement server-side
Computeengine is a remote object on a server that accepts tasks from the client and returns results after performing the task. These tasks are performed on machines running on the server. This type of distributed application enables many clients to use a powerful machine or a machine with special hardware resources.
The peculiarity of Computeengine is that the task it runs does not need to be defined when it writes code or runs. New tasks can be created at any time and then handed over to them. The only requirement for a task is that the task class must implement a specific interface. The code for the task to be completed can be downloaded to Computeengine by the RMI system. Then Computeengine runs this task, using the resources on the machine that the Computeengine is running on.
The ability to perform arbitrary tasks is ensured by the dynamic nature of the Java platform, which is extended to the network world by RMI. RMI dynamically loads the task code into the JVM where the computeengine resides, and then runs the task without having to know the class that implements the task in advance. Such an application with the ability to dynamically load code is often referred to as behavior-based application. This application typically requires the infrastructure to allow the proxy. With RMI, this application forms the basic mechanism of distributed computing on the Java platform.
L Design Remote Interface
The Compute.compute interface defines the remote accessible part, and the following is the source code for the compute interface. By inheriting the Java.rmi.Remote interface, the compute interface indicates that it is an interface that the interface method can be called by another JVM. So the object that implements the interface is the remote object.
Package compute;
Import Java.rmi.Remote;
Import java.rmi.RemoteException;
Public interface Compute extends Remote {
T ExecuteTask (Task t) throws remoteexception;
}
As a member of the remote interface, the ExecuteTask method is a remote method. Therefore, the method needs to be defined as being able to throw java.rmi.RemoteException exceptions. This exception is thrown when a remote method is called by the RMI system, indicating that the communication failed or a protocol error occurred. RemoteException is a checked exception, so any code that calls a remote method needs to handle the exception, either to catch the exception or to declare the throw clause.
The second interface required by Computeengine is the task interface, which is also the type parameter of the ExecuteTask. The Compute.task interface defines the Computeengine and the direct interface that it will perform, providing a way to begin the work. The following is the source code for the task interface:
Package compute;
Public interface Task {
T execute ();
}
The task interface defines a method, execute, no arguments, and no exceptions. Because this interface does not inherit the remote interface, the method does not have to declare the throw java.rmi.RemoteException clause.
RMI uses the Java object serialization mechanism to transfer objects in a value-passing manner between JVMs. To be able to serialize an object requires implementation of the Java.io.Serializable identity interface, so the class that implements the task interface also implements the Java.io.Serializable interface, and the class of the object that is the result of the task execution must also implement this interface.
Different kinds of tasks can be performed by a compute object, as long as these tasks implement the task interface type. The class that implements this interface can contain any data that is required to perform the calculation and other methods that are required to perform the calculation.
RMI assumes that the task object is written by the Java language Program, computeengine the implementation of a previously unknown task object, and, when needed, is downloaded from RMI to the JVM where Computeengine resides. This capability allows Computeengine's client to define new tasks to be run on the server without the need for the code to be explicitly installed on the server machine.
L Implement Computeengine Class (service Class)
In summary, a class that implements a remote interface requires at least the following steps:
? Declaring the remote interface to be implemented
? Define constructors for each remote object
? Implementation of remote Call method in remote interface
An RMI server-side program needs to create the initial remote objects and publish them to the RMI environment so that they can accept remote calls. This step can be included in a method of a remote object, or in an entity object in another class. This step is done in the following steps:
? Create and install a security manager
? Create and publish one or more remote objects
? Register at least one remote object using RMI registry
The purpose of implementing the security Manager is for the RMI framework to utilize the Java Security Manager to ensure the security of remote method calls.
The following is the full implementation of Computeengine. This class implements the remote Call Interface (interface) Compute and the Main method, which is used to install the Compute engine. Here is the source code for this class:
PackageEngineImportJava.rmi.RemoteException;ImportJava.rmi.registry.LocateRegistry;ImportJava.rmi.registry.Registry;ImportJava.rmi.server.UnicastRemoteObject;ImportCompute.compute;ImportCompute. Task; Public class computeengine implements Compute { Public Computeengine() {Super(); } Public<T> TExecuteTask(task<t> T) {returnT.execute (); } Public Static void Main(string[] args) {if(System.getsecuritymanager () = =NULL) {System.setsecuritymanager (NewSecurityManager ()); }Try{String name ="Compute"; Compute engine =NewComputeengine ();//Use an anonymous port to export the remote object so that it can receive incoming calls. //Returns stub for remote objectCompute stub = (Compute) unicastremoteobject.exportobject (engine); Registry Registry = Locateregistry.getregistry (); Registry.rebind (name, stub); System.out.println ("Computeengine Bound"); }Catch(Exception e) {System.err.println ("Computeengine exception:"); E.printstacktrace (); } }}
The remote method requires a parameter or a return value that can be almost any object, including local objects, remote objects, and meta data types. More specifically, any entity object can be a parameter or return value that is available as a remote object as long as instances of the following types include a metadata type, a remote object, or a serializable object (an object that implements Java.io.Serializable).
Some object types do not meet the requirements above, so they cannot be passed to a remote method as a parameter, or as a return value of a remote method. These objects, such as threads or file descriptors, are meaningful only within a single address space, and many of the core classes implement the Serializable interface.
How to pass parameters and get return values follows the following conventions:
? A remote object is essentially passed by reference. A reference to a remote object is contained in the stub object corresponding to this object, and is passed as the stub object when registered with the registry, and the client obtains the stub object by name in the registered lookup. This stub can act as a proxy for a client that implements a remote interface.
? Local objects are passed by value copy, which uses the technique of object serialization. The default copy method is to copy all domains except those that are identified as static and transient. The default serialization behavior can be overloaded.
Passing a remote object by reference means that all modifications to the state of the object will affect the original remote object. When a remote object reference is passed, only the method provided by the remote interface can be used by the receiver. Any method defined in the implementation class or defined in a non-remote interface that is implemented by a class is not available on the receiving side.
In the parameter return value of a remote method call, an object of a non-remote object is passed through a value copy. Therefore, a copy of an object is created in the JVM of the receiving end. Any change to the state of an object affects only the copied object, without affecting the original object instance on the sending side. Any change to the state of an object by the sending side affects only the instance of the originating object on the sender, without affecting the copy object of the object on the receiving end.
L Implement server (completed by the main method in the service class)
The most complex code in Computeengine is the main method. The main method is used to start computeengien so necessary initialization is required to prepare the server for accepting client requests. This method is not a remote method, that is, it cannot be called by another JVM. Because the main method is declared static, this method is not associated with an object and is only associated with the Computeengine class.
Java Learning Note RMI Remote method invocation