Explain RMI with a suitable program.

Java RMI (Remote Method Invocation) Explained with Example Program

Remote Method Invocation (RMI) in Java allows a program to call methods on an object running in another Java Virtual Machine (JVM), possibly on a different computer. It simplifies distributed computing by making remote calls look like normal method calls.

What is RMI?

  • RMI stands for Remote Method Invocation.
  • It enables communication between Java objects across a network.
  • Remote methods are invoked using stubs (client-side proxies) generated dynamically at runtime.
  • RMI uses the Java Remote Method Protocol (JRMP) underneath.

Key Components

  • Remote Interface: Declares methods that can be called remotely. It extends java.rmi.Remote and methods throw RemoteException.
  • Remote Object (Implementation): Implements the remote interface and is exported using UnicastRemoteObject.
  • RMI Registry: A simple naming service where the server registers the remote object with a name.
  • Client: Looks up the remote object by name in the registry and invokes methods.

How RMI Works (Flow)

  1. Define a remote interface.
  2. Provide a class that implements the interface and exports the object.
  3. Start or connect to the RMI Registry and bind the remote object with a name.
  4. On the client side, look up the name in the registry to get a stub.
  5. Call methods on the stub as if it were a local object; the call is executed on the server.

Complete Java RMI Program: Adder Service

This example shows a simple distributed calculator that adds two integers using RMI.

1) Remote Interface (AdderService.java)

// AdderService.java
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface AdderService extends Remote {
    int add(int a, int b) throws RemoteException;
}

2) Remote Implementation (AdderServiceImpl.java)

// AdderServiceImpl.java
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class AdderServiceImpl extends UnicastRemoteObject implements AdderService {

    // Export the remote object
    protected AdderServiceImpl() throws RemoteException {
        super();
    }

    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
}

3) Server: Create and Bind Remote Object (AdderServer.java)

// AdderServer.java
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.ExportException;

public class AdderServer {
    public static void main(String[] args) {
        try {
            // Create the remote service
            AdderService service = new AdderServiceImpl();

            // Start RMI registry on port 1099 if not already running
            Registry registry;
            try {
                registry = LocateRegistry.createRegistry(1099);
                System.out.println("RMI registry started on port 1099");
            } catch (ExportException e) {
                registry = LocateRegistry.getRegistry(1099);
                System.out.println("RMI registry already running");
            }

            // Bind the service with a name
            registry.rebind("AdderService", service);
            System.out.println("AdderService bound. Server ready.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4) Client: Lookup and Use the Remote Service (AdderClient.java)

// AdderClient.java
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class AdderClient {
    public static void main(String[] args) {
        try {
            // Connect to registry on localhost (use server IP if remote)
            Registry registry = LocateRegistry.getRegistry("localhost", 1099);

            // Lookup the remote object
            AdderService service = (AdderService) registry.lookup("AdderService");

            // Invoke remote method
            int result = service.add(12, 18);
            System.out.println("12 + 18 = " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

How to Compile and Run

  1. Place all four files in the same folder. Ensure both server and client have access to the AdderService interface.
  2. Compile:
    javac *.java
  3. Run the server (starts the registry and binds the object):
    java AdderServer
  4. In another terminal, run the client:
    java AdderClient

Expected Output (Client)

12 + 18 = 30

Notes and Tips

  • No manual stub generation is needed in modern Java; dynamic proxies are used.
  • If running on different machines, replace localhost with the server’s IP in the client code and ensure port 1099 is open.
  • Both client and server must have the remote interface class available on their classpath.

Where RMI is Useful

  • Distributed systems where Java-to-Java communication is preferred.
  • Simple client-server applications, remote administration tools, and academic projects.