A Quick Peek Into Java Remote Method Invocation(RMI)

SENG 41283 — Distributed and Cloud Computing

Nipun Thennakoon
3 min readJul 18, 2020

What is Java RMI?

Invoking a method on a remote object is typically known as remote method invocation(RMI) and Java RMI is the Java API that lets an object residing in a one JVM to invoke the methods on another object which is running on a different JVM.

Typical implementation model of Java-RMI using stub and skeleton objects

So, what are stubs, skeletons and remote objects?

Remote Object

An object whose methods can be called from another JVM is known as a remote object. In distributed systems, client programs calls on the methods on a remote object to get the services offered by the remote object.

Stub

A stub is a kind of like a gateway for the client-side. All the communication that happens back and forth between the client and server are routed through the stub. A stub represents the remote object and resides in the client-side. In other words, the client program can call the methods on the stub like it’s the remote object and the stub forwards them to the actual remote object (through skeleton) and returns the results to the caller.

Skeleton

A skeleton is in the server side and act as a gateway for the server side objects. All the incoming client requests are routed through the skeleton and when it receive an incoming request, it invokes the method on actual remote object and transmit the results to the caller.

Now that we understand the basics of RMI, let’s look at a how we can implement an RMI application which can do basic math operations on two integers on a remote server.

  1. First, let’s define the remote interface. This will be used by both client and server to refer the remote object.
// Calculator.javaimport java.rmi.*;public interface Calculator extends Remote
{
int add(int x,int y) throws RemoteException;
int subtract(int x,int y) throws RemoteException;
int multiply(int x,int y) throws RemoteException;
int divide(int x, int y) throws RemoteException;
}

2. Next, we can implement the methods defined in the remote interface.

// CalculatorImpl.javaimport java.rmi.*;
import java.rmi.server.*;
public class CalculatorImpl extends UnicastRemoteObject implements Calculator
{
public CalculatorImpl() throws RemoteException
{
super();
}
public int add(int x, int y)
{
return x + y;
}
public int subtract(int x, int y)
{
return x - y;
}
public int multiply(int x, int y)
{
return x * y;
}
public int divide(int x, int y)
{
if(y != 0)
{
return x / y;
}
else
{
return -1;
}
}
}

3. Third step is to generate the stub and skeleton using the Java RMI compiler. First you need to compile your remote interface and implementation. Then run

rmic CalculatorImpl

in your working directory.

4. Then we can create the server.

// Server.javaimport java.rmi.*;
import java.rmi.registry.*;
public class Server
{
public static void main(String[] args)
{
try
{
Calculator stub = new CalculatorImpl();
Naming.rebind("rmi://localhost:5000/calculate", stub);
} catch (Exception e)
{
System.out.println(e.toString());
}
}
}

5. And then, create the client application.

// Client.javaimport java.rmi.*;public class Client
{
public static void main(String[] args)
{
int x = 15, y = 5;
try
{
Calculator stub = (Calculator) Naming.lookup("rmi://localhost:5000/calculate");

System.out.println("x = " + x + "| y = " + y);
System.out.println("x + y: " + stub.add(x, y));
System.out.println("x - y: " + stub.subtract(x, y));
System.out.println("x * y: " + stub.multiply(x, y));
System.out.println("x / y: " + stub.divide(x, y));
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
}

To run the thing we will need three shells:

  1. Start the registry server using at port 5000 in the first shell,
rmiregistry 5000

2. Start the Server in the second shell.

java Server

3. Run the client application in the third shell.

java Client

and you’ll see the correct output in the client shell.

--

--