importjava.rmi.*;importjava.rmi.server.UnicastRemoteObject;importjava.rmi.dgc.*;publicclassRMIServer{privateRMIServerImpl impl;publicRMIServer()throwsRemoteException{ impl =newRMIServerImpl();UnicastRemoteObject.exportObject(impl,0);}publicstaticvoidmain(String[]args){try{RMIServer server =newRMIServer();System.out.println("Server started");Runtime.getRuntime().addShutdownHook(new Thread(()->{try{UnicastRemoteObject.unexportObject(server.impl,true);}catch(Exceptione){e.printStackTrace();}}));}catch(Exceptione){e.printStackTrace();}}}classRMIServerImplimplementsRMIInterface{@OverridepublicStringgetMessage(){return"Hello from the server";}}
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.dgc.*;
public class RMIClient {
public static void main(String[] args) {
try {
// Lookup the registry
Registry registry = LocateRegistry.getRegistry();
// Get the remote object reference
RMIInterface server = (RMIInterface) registry.lookup("rmiServer");
// Create a lease checker to monitor the server's lease
LeaseChecker leaseChecker = new LeaseChecker((RMIServerImpl) server);
// Start the lease checker thread
leaseChecker.start();
// Make a call to the server
System.out.println(server.getMessage());
// Wait for a few seconds to allow the lease to expire
Thread.sleep(6000);
// Check if the lease has expired
if (leaseChecker.isExpired()) {
System.out.println("Lease expired");
} else {
System.out.println("Lease still active");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class LeaseChecker extends Thread {
private RMIServerImpl server;
private boolean expired;
public LeaseChecker(RMIServerImpl server) {
this.server = server;
}
@Override
public void run() {
try {
// Get the server's lease
Lease lease = server.getLease();
// Monitor the lease until it expires or is renewed
while (true) {
// Check if the lease has expired
if (lease.expired()) {
expired = true;
break;
}
// Renew the lease if it is close to expiring
if (lease.getRemainingLeaseTime() < 3000) {
lease = server.renewLease();
}
// Sleep for a second to reduce CPU usage
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isExpired() {
return expired;
}
}
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.dgc.*;
import java.util.*;
public class RMIServerCleaner implements RMICleaner, Remote {
private Map<Long, Lease> leases = new HashMap<>();
@Override
public Lease renewLease(Remote ref, long value, long leaseDuration) throws RemoteException {
long leaseId = ref.hashCode();
synchronized (leases) {
leases.put(leaseId, new Lease(value, leaseDuration));
}
return new Lease(value, leaseDuration);
}
@Override
public void clean(long leaseId, long renewId, Remote ref) {
synchronized (leases) {
leases.remove(leaseId);
}
}
@Override
public void unexportObject(Remote ref, boolean force) {
long leaseId = ref.hashCode();
synchronized (leases) {
leases.remove(leaseId);
}
}
}
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.dgc.*;
import java.lang.ref.*;
public class RMICustomClient {
public static void main(String[] args) {
try {
// Lookup the registry
Registry registry = LocateRegistry.getRegistry();
// Create a custom remote reference
RMICustomReference reference = new RMICustomReference();
// Get the remote object reference
RMIInterface server = (RMIInterface) reference.getRemote(registry, "rmiServer");
// Make a call to the server
System.out.println(server.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
class RMICustomReference extends WeakReference<Remote> implements RemoteReference {
private long leaseId;
private RMIDGCServer server;
public RMICustomReference() {
super(null);
}
public RMICustomReference(Remote obj, RMIDGCServer server) {
super(obj);
this.server = server;
long leaseId = server.lease(this, 60000, 120000);
this.leaseId = leaseId;
}
@Override
public Remote getRemote() {
return super.get();
}
@Override
public long getLeaseId() {
return leaseId;
}
@Override
public void renewLease(long value) {
server.renewLease(leaseId, value);
}
}
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.dgc.*;
import java.util.*;
public class RMICustomDGCServer extends RMIDGCServer, UnicastRemoteObject {
private Map<Long, Lease> leases = new HashMap<>();
public RMICustomDGCServer() throws RemoteException {
super();
}
@Override
public Lease renewLease(Remote ref, long value, long leaseDuration) throws RemoteException {
long leaseId = ref.hashCode();
synchronized (leases) {
leases.put(leaseId, new Lease(value, leaseDuration));
}
return new Lease(value, leaseDuration);
}
@Override
public void clean(long leaseId, long renewId, Remote ref) {
synchronized (leases) {
leases.remove(leaseId);
}
}
}