SYSTEM SOFTWARE 1
RMI - Remote Method Invocation
SYSTEM SOFTWARE 2
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 3
Motivation
Normal method calls
Based on object references
within JVM
Remote methods calls
Method calls between
objects in different JVMs
Requires a “remote-
reference”
client server
request
response
client server
request
response
JVM 2JVM 1
request
response
SYSTEM SOFTWARE 4
Problems with Remote Method Invocations
Object references
What is a remote reference?
How can one get a reference to an object in a different?
Method calls
How can the jump address of remote method be determined?
Parameter passing and return values
How are parameter passed and values returned from a remote method?
Object creation
How can one create an object in a remote JVM?
Garbage collection
When can a remote object be garbage collection?
Class loading
How and from where can the class of a remote object be loaded?
SYSTEM SOFTWARE 5
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 6
Proxy Pattern
Subject interface
interface the client sees and the server has to implement
Subject implementation
implements interface to provide functions
Subject proxy
used by client
implements interface by delegating requests to real implementation
Clientrequest()
SYSTEM SOFTWARE 7
Proxy Pattern in RMI
Stub represents proxy for client
Proxy sends requests over network to server
Skeleton receives requests and forwards request to server implementation
Server handles requests
Results is sent back by skeleton
Stub returns result to client
clientserver
request
response
JVM 1JVM 2
request
response
server_stubserver_skeleton
Proxy
SYSTEM SOFTWARE 8
Communication Architecture
Client and server applications
Stubs and skeletons
Remote reference layer
Network connection
Network connection based on TCP/IP sockets
JVM JVM JVM JVM
SYSTEM SOFTWARE 9
Remote Object Registration and Lookup
Registry service support
Registration of remote objects with RMI-URL
Lookup for remote objects
Provided by
RMI registration service utility rmiregistry
RMI service classes Naming, Registry, and LocateRegistry
SYSTEM SOFTWARE 10
Remote Object Registration and Lookup: Approach
LocateRegistry: Access to registry service
Registration: bind or rebind for registration of a remote object
Must provide a unique id for the object.
Remote object then is registered with unique RMI-URL
rmi://<HostComputer>:1099/Bank
Client can access remote object from server using unique name
try {
Bank bank = new BankImpl();
Registry reg = LocateRegistry.createRegistry(1099);
reg.bind("Bank", bank);
}
...
// Client
try {
Registry reg = LocateRegistry.getRegistry("<Hostcomputer>", 1099);
Bank bank = (Bank) reg.lookup("Bank");
...
}
...
default port 1099, others allowed
unique object name
unique object name
server and port
SYSTEM SOFTWARE 11
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 12
Implementation of Remote Objects
Interfaces and classes
Interface for remote object
must extend interface java.rmi.Remote
declares public methods for remote object
methods must be declared to throw RemoteException
Server object implementation
must implement interface
must be exported to RMI system
Stub (since Java 1.5 by dynamic proxy)
implements Interface
extends java.rmi.server.RemoteStub
explicitly created by rmic compiler,
or since Java 1.5 by dynamic proxy
Skeleton (only used in Java 1.1)
extends java.rmi.server.Skeleton
explicitly created by rmic compiler,
or since Java 1.1 by dynamic proxy
ServerImpl
«Schnittstelle»
ServerSpec
ServerImpl_Skel
«Schnittstelle»
java.rmi.server.Skeleton
«Schnittstelle»
java.rmi.Remote
+()
+changed()
ServerImpl_Stub
java.rmi.server.RemoteStub
since Java 1.5 also as
Dynamic Proxy
SYSTEM SOFTWARE 13
Example Bank Server
The following example shows the implementation of a RMI
The following steps are required
Developing the application
Definition of interfaces for remote objects
Implementation of interface for server application
Generation for stub and skeleton classes (can be omitted since Java 1.5)
Implementation of server main program which creates and registers server object
Implementation of client program which accesses remote object
Start application
Start of rmiregistry (not required since Java 1.5)
Start of server program
Start of client program
SYSTEM SOFTWARE 14
Example Bank Server: Interface Bank
Interface Bank defines methods for working with accounts
package bank.common;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Bank extends Remote {
public static final int PORT = 1099;
public long getBalance(int account)
throws RemoteException;
public void deposit(int account, long amount)
throws RemoteException;
public boolean transfer(int from, int to, long amount)
throws RemoteException;
}
RemoteExceptions for all remote methods required!
SYSTEM SOFTWARE 15
Example Bank Server: BankImpl
Class BankImpl implements interfaces
should extend UnicastRemoteObject
package bank.server;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import bank.common.Bank;
public class BankImpl extends UnicastRemoteObject implements Bank {
private long[] accounts = new long[100];
protected BankImpl() throws RemoteException { super(); }
public synchronized long getBalance(int account) throws RemoteException {
return accounts[account];
}
public synchronized void deposit(int account, long amount)
throws RemoteException {
accounts[account] += amount;
}
public synchronized boolean transfer(int from, int to, long amount)
throws RemoteException {
accounts[from] -= amount;
accounts[to] += amount;
return true;
}
}
Constructor withRemoteException!
Extending UnicastRemoteObject!
SYSTEM SOFTWARE 16
Example Bank Server: Stub and Skeleton
Stub and skeleton classes are created by
rmi-compiler program
rmic
Or since 1.5 are created dynamically as
dynamic proxies (see below)
rmic <options> <class names> where <options> includes: -keep Do not delete intermediate generated source files -g Generate debugging info -depend Recompile out-of-date files recursively -nowarn Generate no warnings -verbose Output messages about what the compiler is doing -classpath <path> Specify where to find input source and
class files -d <directory> Specify where to place generated class
files -J<runtime flag> Pass argument to the java interpreter-v1.1 Create stubs/skeletons for JDK 1.1 stub protocol
version -vcompat (default) Create stubs/skeletons compatible with
both JDK 1.1 and Java 2 stub protocol versions -v1.2 Create stubs for Java 2 stub protocol version only
> rmic –keep BankImpl
public final class BankImpl_Stub
extends java.rmi.server.RemoteStub
implements Bank, java.rmi.Remote
{
...
}
public final class BankImpl_Skel
implements java.rmi.server.Skeleton
{
...
}
SYSTEM SOFTWARE 17
Example Bank Server: Server Program
Server program must
create remote object implementation
export it to RMI registry
register it under unique URL
package bank.server;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import bank.common.Bank;
public class BankServer {
public BankServer() {
try {
Bank bank = new BankImpl();
Registry reg = LocateRegistry.createRegistry(Bank.PORT);
reg.bind("Bank", bank);
} catch (Exception e) {
System.out.println("Trouble: " + e);
}
}
public static void main(String args[]) {
new BankServer();
}
}
SYSTEM SOFTWARE 18
Example Bank Server: Client Program
Client program will retrieve remote object from RMI registry using URL
call remote method (by calling methods of stub)
catch exceptions
package bank.client;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import bank.common.Bank;
public class BankClient {
public static void main(String[] args) {
try {
Registry reg = LocateRegistry.getRegistry("…Server Adr…", Bank.PORT);
Bank bank = (Bank) reg.lookup("Bank");
bank.deposit(1, 10000);
bank.deposit(2, 20000);
boolean success = bank.transfer(1, 2, 3000);
if (success) {
System.out.println(bank.getBalance(1));
System.out.println(bank.getBalance(2));
} else { … }
} catch (Exception e) {
…
}
}
}
Name of server, e.g., "localhost"
SYSTEM SOFTWARE 19
Exporting Remote Objects
Remote objects must be exported to RMI system
2 possibilities
Extending UnicastRemoteObject then export is done in constructor of this base class
With static method exportObject of UnicastRemoteObject
public class BankImpl implements Bank { ... }
public class BankServer {
private Bank bank;
public BankServer() {
try {
bank = new BankImpl();
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
Remote rstub = UnicastRemoteObject.exportObject(bank, Bank.PORT);
reg.bind("Bank", bank);
} catch (Exception e) {
System.out.println("Trouble: " + e);
}
...
static Remote exportObject(Remote obj, int port) throws RemoteException
SYSTEM SOFTWARE 20
Unexporting Remote Objects
Remote objects can be unexported from RMI (when no longer needed)
with static method unexportObject of UnicastRemoteObject
public class BankServer {
private Bank bank;
public start() {
try {
bank = new BankImpl();
Registry reg = LocateRegistry.createRegistry(PORT);
RemoteStub bstub = UnicastRemoteObject.export(bank);
reg.bind("Bank", bstub);
} catch (Exception e) {
System.out.println("Trouble: " + e);
}
}
public static void main(String[] args) throws Exception {
new BankServer().start();
// wait for termination
…
UnicastRemoteObject.unexportObject(bank, true);
}
public static boolean unexportObject(Remote obj, boolean force)
throws java.rmi.NoSuchObjectException
SYSTEM SOFTWARE 23
RMI
Excursion: Dynamic Proxy
SYSTEM SOFTWARE 24
Excursion: Dynamic Proxy
package java.lang.reflect
Dynamic Proxy allows creating object which implements list of interfaces
and delegates method calls to an InvocationHandler
created by static method Proxy.newProxyInstance
Created proxy object now implements interfaces by calling invoke of InvocationHandler
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
}
public class Proxy {
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException;
…
}
Foo f = (Foo)Proxy.newProxyInstance(null, new Class[] {Foo.class}, handler);
Application:
Implementedinterfaces
InvocationHandler
Reflection API
SYSTEM SOFTWARE 25
Example Dynamic Proxy: TraceHandler (1/2)
TraceHandler implements InvocationHandler
prints out a trace message
then calls real method
class TraceHandler implements InvocationHandler {private Object target;private PrintStream traceLog;
public TraceHandler(Object target, PrintStream traceLog) { this.target = target;this.traceLog = traceLog;
}public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable { traceLog.print(target + "." + m.getName() + "(");if (args != null) {
for (int i = 0; i < args.length; i++) { traceLog.print(args[i]);if (i < args.length - 1)
traceLog.print(", ");}
}traceLog.println(")");
return m.invoke(target, args);}
}
Output of trace info
Call of real method using reflection API
SYSTEM SOFTWARE 26
Example Dynamic Proxy: TraceHandler (2/2)
Test of Proxy for Integer values which implement Comparable interface
Trace of compareTo method of Comparable
public class ProxyTest {
public static void main(String[] args) { Object[] elements = new Object[1000];// fill elements with proxies for the integers 1 ... 1000for (int i = 0; i < elements.length; i++) {
Integer value = i + 1;Class[] interfaces = value.getClass().getInterfaces();InvocationHandler handler = new TraceHandler(value, System.out);Object proxy = Proxy.newProxyInstance(null, interfaces, handler);elements[i] = proxy;
}
Integer key = 547; // search for the keyint result = Arrays.binarySearch(elements, key);
// print match if foundif (result >= 0)
System.out.println(elements[result]);}
}
500.compareTo(547)750.compareTo(547)625.compareTo(547)562.compareTo(547)531.compareTo(547)546.compareTo(547)554.compareTo(547)550.compareTo(547)548.compareTo(547)547.compareTo(547)..547
{ Comparable.class }
SYSTEM SOFTWARE 27
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 28
Parameter Passing and Return Values
Must marshall and unmarshall parameters and return values for network
transfer
boolean success = bank.transfer(1, 2, 3000);
transfer(1,2,3000)
JVM 1
true111…
0101001001101
:BankClient :Bank_Stub
transfer(1,2,3000)
JVM 1
true
:Bank_Skeleton :Bank_Impl
marshall unmarshall
marshallunmarshall
SYSTEM SOFTWARE 29
Parameter Passing and Return Values
Marshalling dependent on type of values
Built-in data types (int, double, boolean, char etc.) are transferred as is in byte stream
Serializable objects (implement interface Serializable) objects get serialized by internal serialization mechanism
and on the other side a copy is created by deserializing it
Remote objects (implement interface Remote) a stub is created at the client side
all others (not serializable and not remote) cannot be used as parameters or return values in remote method calls
Object serialization: see slides on InputOutput streaming
SYSTEM SOFTWARE 30
Marshalling Serializable Objects
Serializable objects implement interface Serializableobject information and (non-transient) fields will be serialized
Deserialize object from stream at client side
public class AccountInfo implements Serializable {private final int id; private final String owner; private final long balance;
public AccountInfo(int id, String owner, long balance) {…}…
}
public interface Bank extends Remote {…public AccountInfo getAccountInfo(int accountNumber) throws RemoteException;
}
public class BankClient {public static void main(String[] args) {
try {…AccountInfo info = bank.getAccountInfo(acc1.getId()); …
deserialized object
SYSTEM SOFTWARE 31
Marshalling Serializable Objects
Will serialize object into byte stream
transfer byte stream
deserialize and create new object from byte stream
Info info = getAccountInfo(id)
JVM 1
:AccountInfo 0101001001101
:BankClient :Bank_Stub
getAccountInfo(id)
JVM 1
:Bank_Skeleton :Bank_Impl
:AccountInfo
Info info = getAccountInfo(id)
:AccountInfo 0101001001101
getAccountInfo(id)
:AccountInfo
serializedeserialize
new object created
SYSTEM SOFTWARE 32
Serializable / Not Serializable Data Types
Serializable :
built-in data types (int, boolean, double, …)
arrays with serializable element type
String
Collections: ArrayList, LinkedList, TreeSet, …
Calendar, Date, etc.
…
Example of not serializable types :
Thread, ClassLoader, etc. Objects local to the VM
InputStream, Socket, etc. Objects accessing os resources
…
SYSTEM SOFTWARE 33
Marshalling Remote Objects
Not the object values is transmitted
but a remote reference is created by RMI system
client server
remote
JVM 2JVM 1
server_stub server_skeleton
Remote-Reference to
remote
getRemoteMember() getRemoteMember()
remote_stub
remote
create()
remote_stub
SYSTEM SOFTWARE 34
Extended Bank Example
Remote objects Account Customer Bank with extended interface
public interface Account extends Remote {
public int getId() throws RemoteException;
public Customer getCustomer() throws RemoteException;
public long getBalance() throws RemoteException;
public long withdraw(long amount) throws RemoteException;
public void deposit(long diff) throws RemoteException;
}
public interface Customer extends Remote {
public String getName() throws RemoteException;
public Account[] getAccounts() throws RemoteException;
}
public interface Bank extends Remote {
public Customer getCustomer(String name) throws RemoteException;
public Customer createCustomer(String name) throws RemoteException;
public Account getAccount(int accountNumber) throws RemoteException;
public Account createAccount(String customer) throws RemoteException;
public void transfer(int from, int to, long amount) throws RemoteException;
}
methods return remote objects
SYSTEM SOFTWARE 35
Extended Bank Example: BankImpl
BankImpl stores sets of customers and accounts
and provides access to customers and accounts
public class BankImpl extends UnicastRemoteObject implements Bank {
private static BankImpl instance;
public synchronized static Bank getInstance() {
if (instance == null) {
try { instance = new BankImpl();
} catch (RemoteException e) { }
}
return instance;
}
private static int id = 0;
private final Map<Integer, AccountImpl> accounts;
private final Map<String, CustomerImpl> customers;
private BankImpl() throws RemoteException {
accounts = new HashMap<Integer, Account>();
customers = new HashMap<String, Customer>();
}
@Override
public synchronized Customer getCustomer(String name) throws RemoteException {
return customers.get(name);
}
@Override
public synchronized Account getAccount(int id) throws RemoteException {
return accounts.get(id);
}
...
SYSTEM SOFTWARE 36
Extended Bank Example: CustomerImpl
public class CustomerImpl extends UnicastRemoteObject implements Customer {
private final String name;
final List<Account> accounts;
protected CustomerImpl(String name) throws RemoteException {
super();
this.name = name;
this.accounts = new ArrayList<Account>();
}
@Override
public String getName() throws RemoteException {
return name;
}
@Override
public synchronized Account[] getAccounts() throws RemoteException {
return accounts.toArray(new Account[0]);
}
}
SYSTEM SOFTWARE 37
Extended Bank Example: AccountImpl
public class AccountImpl extends UnicastRemoteObject implements Account {
private final int id;
private final String customer;
private long balance;
public AccountImpl(int id, String customer) throws RemoteException {
super();
this.id = id;
this.customer = customer;
balance = 0L;
}
@Override
public int getId() throws RemoteException {
return id;
}
@Override
public Customer getCustomer() throws RemoteException {
return BankImpl.getInstance().getCustomer(customer);
}
@Override
public synchronized long getBalance() throws RemoteException {
return balance;
}
…
}
SYSTEM SOFTWARE 38
Extended Bank Example: Server Program
Server program registers Bank as single access point
public class BankServer {
private static Bank bank;
private static void start() throws Exception {
bank = BankImpl.getInstance();
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
reg.bind("Bank", bank);
System.out.println("Server started on port " + Registry.REGISTRY_PORT);
}
public static void main(String[] args) throws Exception {
start();
…
}
SYSTEM SOFTWARE 39
Extended Bank Example: Client Program
Client program then retrieves Bank from RMI registry
other remote objects, Customers and Accounts, are then retrieved from Bank
public class BankClient {
…
public static void main(String[] args) {
try {
Registry reg = LocateRegistry.getRegistry("localhost", Bank.PORT);
Bank bank = (Bank) reg.lookup("Bank");
Customer cust1 = bank.createCustomer("Berger");
Customer cust2 = bank.createCustomer("Maier");
Account acc1 = bank.createAccount("Berger");
Account acc2 = bank.createAccount("Maier");
acc1.deposit(10000);
acc2.deposit(20000);
boolean success = bank.transfer(acc1.getId(), acc2.getId(), 3000);
if (success) {
System.out.println(acc1.getBalance());
System.out.println(acc2.getBalance());
} else {
System.out.println("Transfer not successful");
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
retrieve Bank
Create and access remote objects Customer and Account
from Bank
SYSTEM SOFTWARE 40
Combining Serializable and Remote Objects
When a Serializable object contains a remote object, the deserialized
object will contain a Stub to the remote object
Note: Remote object reference in a Serializable object can be problematic
public class RemoteAccountEvent extends EventObject implements Serializable {private final Account account;
public RemoteAccountEvent(Account source) { super(source);
}…
}
public interface Customer extends Remote {
public Account[] getAccounts() throws RemoteException;
}
public class BankClient {
public static void main(String[] args) {
try {
…
Account[] accounts = customer.getAccounts();
array of stubs
array Serializable, Account Remote
NOT A GOOD IDEA!! Event object contains remote stub!
SYSTEM SOFTWARE 41
== and equals for Serializable Objects
== of serialized objects
with every remote access a new object is created by deserialization
equals when Serializable object implements equals
public class BankClient_Equals {
public static void main(String[] args) {
try {
Customer berger = bank.getCustomer("Berger");
String name1 = berger.getName();
String name2 = berger.getName();
if (name1.equals(name2)) {true !!!
public class BankClient_Equals {
public static void main(String[] args) {
try {
Customer berger = bank.getCustomer("Berger");
String name1 = berger.getName();
String name2 = berger.getName();
if (name1 == name2) { false !!!
SYSTEM SOFTWARE 42
== and equals for Remote References
== of remote references
with every remote access an new stub is created
Stub objects are not ==
equals of remote references
• Stub implements equals so that stubs of same remote objects are equals
Stub objects are equals when stubs reference same remote object
public class BankClient_Equals {
public static void main(String[] args) {
try {
Customer cust1 = bank.getCustomer("Berger");
Customer cust2 = bank.getCustomer("Berger");
if (cust1.equals(cust2)) { true !!!
public class BankClient_Equals {
public static void main(String[] args) {
try {
Customer cust1 = bank.getCustomer("Berger");
Customer cust2 = bank.getCustomer("Berger");
if (cust1 == cust2) { false !!!
SYSTEM SOFTWARE 43
== and equals for Remote References
CustomerImpl implements equals has no effect on client
Server CarStore erzeugt immer neue CarImpl-Objekte
Diese Objekte werden am Client nicht als equals erkannt
public class BankClient_Equals {
public static void main(String[] args) {
try {
Customer berger1 = bank.getCustomer("Berger");
Customer berger2 = bank.getCustomer("Berger");
if (cust1.equals(cust2)) {
public class CustomerImpl extends UnicastRemoteObject implements Customer {
...
public synchronized boolean equals(Object obj) {
if (obj instanceof CustomerImpl) {
return name.equals((CustomerImpl) obj).name;
}
return false;
}
}
public class BankImpl extends UnicastRemoteObject implements Bank {
...
public synchronized Customer getCustomer(String name) throws RemoteException {
return new CustomerImpl(name);
}
false, because equals of stub isused and not same remote object
new Customer objects with same name are created
SYSTEM SOFTWARE 44
Remote References as Parameter
Remote reference as parameter problematic
client retrieves remote object
client hold stub object
when using stub as parameter stub is sent back to server
connection to original remote object lost
better use ids as parameters
client server
JVM 2JVM 1
server_stub server_skeleton
Remote-Reference to
remote_stub
remoteremote_stub
callWithRef(remote_stub) returnRef(remote_stub)
remote_stub
??
public boolean transfer(Account from, Account to, long amount) throws RemoteException;
SYSTEM SOFTWARE 45
Extended Bank Example: Bad transfer Method
public interface Bank extends Remote {
…
public boolean transfer(Account from, Account to, long amount) throws RemoteException;
}
Implementation of remote method
public class BankImpl extends UnicastRemoteObject implements Bank {
…
@Override
public boolean transfer(Account from, Account to, long amount) throws RemoteException {
if (from == to) {
return false; // does not work as expected!!
}
if (! accounts.containsValue(to)) {
return false; // does not work as expected!!
}
return transfer(from.getId(), to.getId(), amount);
}
will always be true
will never become true
must work with ids anyway
SYSTEM SOFTWARE 46
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 47
Callbacks
Callbacks are calls from server to client
e.g., to send clients change notifications
Role of client and server is changed
client must provide a remote object
server has a remote reference
client server
JVM 2JVM 1
server_stub server_skel
Remote-Reference
to client
addChangeListener(client)
client_stub
addChangeListener(client_stub)
changed()
client
implements
Remote !!
client_skel
SYSTEM SOFTWARE 48
Bank Example with Callback
Remote listener interface for client
Account gets add- and removeAccountListener methods
public interface RemoteAccountListener extends Remote {
public void accountChanged(RemoteAccountEvent e) throws RemoteException;
}
public interface Account extends Remote {
…
public void addRemoteAccountListener(RemoteAccountListener l)
throws RemoteException;
public void removeRemoteAccountListener(RemoteAccountListener l)
throws RemoteException;
public class AccountImpl extends UnicastRemoteObject implements Account {
private final List<RemoteAccountListener> listeners = …;
…
@Override
public void addRemoteAccountListener(RemoteAccountListener l) throws RemoteException {
listeners.add(l);
}
@Override
public void removeRemoteAccountListener(RemoteAccountListener l) throws RemoteException
listeners.remove(l);
}
private void fireAccountChanged() { … }
SYSTEM SOFTWARE 49
Bank Example with Callback
Client has to create and register listener object
public class BankClient_Callback {
public static void main(String[] args) {
…
try {
…
acc1Watcher = new AccountWatcher("Berger");
acc2Watcher = new AccountWatcher(“Maier");
acc1.addRemoteAccountListener(acc1Watcher);
acc2.addRemoteAccountListener(acc2Watcher);
acc1.deposit(10000);
acc2.deposit(20000);
boolean success = bank.transfer(acc1.getId(), acc2.getId(), 3000);
…
} catch (Exception e) {
System.out.println("Trouble: " + e);
} finally {
try { acc1.removeRemoteAccountListener(acc1Watcher); } catch (Exception e) {}
try { acc2.removeRemoteAccountListener(acc2Watcher); } catch (RemoteException e) { }
try { UnicastRemoteObject.unexportObject(acc1Watcher, true); } catch (NoSuchObjectException
try { UnicastRemoteObject.unexportObject(acc2Watcher, true);} catch (NoSuchObjectException
}
}
private static class AccountWatcher extends UnicastRemoteObject
implements RemoteAccountListener {
private final String name;
public AccountWatcher(String name) throws RemoteException { … }
public void accountChanged(RemoteAccountEvent e) throws RemoteException { … }
}
}
DO NOT FORGET: removelistener and unexport from RMI!
Listener as remote object
add remote listeners
SYSTEM SOFTWARE 50
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 51
RMI and Threads
Each request executed in its own thread
Synchronization of remote access operations required!!
client 1client 2
Server
request1()
request2()
request3()
Thread
Synchronisation required
SYSTEM SOFTWARE 52
Bank Example: Synchronization
E.g., by synchronization der remote methods
public class BankImpl extends UnicastRemoteObject implements Bank {
...
@Override
public synchronized Customer getCustomer(String name) throws RemoteException {
return customers.get(name);
}
@Override
public synchronized Customer createCustomer(String name) throws RemoteException { … }
@Override
public synchronized Account getAccount(int id) throws RemoteException { … }
@Override
public synchronized Account createAccount(String c) throws RemoteException { … }
...
}
public class AccountImpl extends UnicastRemoteObject implements Account {
private final List<RemoteAccountListener> listeners;
…
public AccountImpl(int id, String customer) throws RemoteException {
this.listeners = new CopyOnWriteArrayList<>();
}
…
thread-safe listener list
synchronized on this
SYSTEM SOFTWARE 53
Problem: Long Running Processes
Long running code blocks whole application
public class BankImpl extends UnicastRemoteObject implements Bank {
...
public synchronized void makeAnnualBalance() {
// long lasting activity
…
}
...
}Long running code blocks
other clients
Solution:
Long running code in background thread!
SYSTEM SOFTWARE 54
Problem: Reentrancy
Java locks are reentrant
i.e., thread which holds lock can enter synchronized code of same lock
public class BankImpl extends UnicastRemoteObject implements Bank {
...
@Override
public synchronized void transfer(int from, int to, long amount) throws RemoteException {
Account aFrom = getAccount(from);
Account aTo = getAccount(to);
…
}
@Override
public synchronized Account getAccount(int id) throws RemoteException { … }
}
with lock to BankImpl
with lock to BankImpl reentrant!
SYSTEM SOFTWARE 55
Problem: Reentrancy
When calling remote methods in callbacks, a different thread will execute
second client request
cannot enter synchronized code and application deadlocks
client 1 Server
request1()
callback()
request2()synchronized(this)
Deadlock because different threads
synchronized(this)
SYSTEM SOFTWARE 56
Problem: Reentrancy
Bank Example: Remote method call in callback
public class BankImpl extends UnicastRemoteObject
...
@Override
public synchronized void transfer(int from, int to, long amount)
Account aFrom = getAccount(from);
Account aTo = getAccount(to);
aTo.fireAccountChanged();
}
@Override
public synchronized Account getAccount(int id) throws RemoteException
}
public class BankClient extends UnicastRemoteObject {
private static class AccountWatcher
extends UnicastRemoteObject implements AccountListener {
public void accountChanged(AccountChangedEvent evt)
throws RemoteException {
bank.getAccount()...
}
};
Thread 1
Thread 2
SYSTEM SOFTWARE 57
Problem: Reentrancy
Solution: Asynchronous Callbacks
client Server
request1()
callback()
synchronized(this)
request2()
synchronized(this)
Callback in asynchronous runnable, non blocking, not synchronized(this)
can terminate
SYSTEM SOFTWARE 58
Problem: Reentrancy
Bank Example: Asynchous execution of callback
public class AccountImpl extends UnicastRemoteObject implements Account {
private final ExecutorService executor = Executors.newFixedThreadPool(10);
...
@Override
public void deposit(long diff) throws RemoteException {
synchronized (this) {
balance = balance + diff;
fireAccountChangedEvent();
}
}
private void fireAccountChanged() {
final AccountChangedEvent evt = new AccoutChangedEvent(…);
for (final AccountListener l : listeners) {
executor.submit(() -> {
l.accountChanged(evt);
});
}
}
…
}
Do callback in asynchronous Runnable
First method can terminate
SYSTEM SOFTWARE 59
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 60
Distributed Garbage Collection
Normal garbage collector frees objects in VM which cannot be accessed
any more
Cannot function for remote objects
Gargabe collector has no reference to remote object
Distributed Garbage Collector works by:
Reference Counting: the references of the remote object by clients are counted
Lease Time: Does a client not access a remote object for some time – the lease time – it is
allowed to collect the memory of the remote object
Clients have to be aware that remote objects can disappear which lead
to exceptions
Lease Time:
System property: java.rmi.dgc.leaseValue
Default value 10 min
Set as VM argument: java –Djava.rmi.dgc.leaseValue=20000
SYSTEM SOFTWARE 61
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 62
Distribution of Code and Class Loading
Dynamic loading of classes in clients
for stubs
for parameter and return values
Example: Stub
client server
remote
JVM 2JVM 1
server_stub server_skeleton
Remote-Reference to
remote
getRemoteMember() getRemoteMember()
remote_stub
remote
create()
remote_stub
Client Server
SYSTEM SOFTWARE 63
Motivation Dynamic Class Loading
public interface Bank extends Remote {
public Customer getCustomer(String customerName) throws RemoteException;
}
Customer
PrivateCustomer BusinessCustomer
public class BankImpl extends UnicastRemoteObject implements Bank {
public synchronized Customer getCustomer(String customerName) throws RemoteException {
if (…) return privateClients.get(customerName);
else return businessClients.get(customerName);
}
There are different subclasses of Customer! Client has to have code for those special classes !
try {
Customer customer = account.getCustomer(name);
} catch (RemoteException remoteException) {
System.err.println(remoteException);
}
Client: There has to be a way that client can load code as needed
Concrete object of type PrivateCustomer_Stub or BusinessCustomer_Stub
SYSTEM SOFTWARE 64
Dynamic Class Loading
Code usually loaded from download folder of Web server
To allow code to be loaded from an external site:
a SecurityManager has to be installed
program has to get permissions as follows
Socket connection to server for RMI connection on port 1099
Socket connection for remote class loading from Web server on port 80 (or 8080)
public class MyClient {
public static void main(String[] args) {
System.setProperty("java.security.policy", "client.policy");
System.setSecurityManager(new SecurityManager());
...
grant {permission java.net.SocketPermission “server-url:1024-65535“, “connect“; permission java.net.SocketPermission “server-url:80“, “connect“;permission java.net.SocketPermission “server-url:8080“, “connect“;
}
Example: Client program:
Policy file for client:
SYSTEM SOFTWARE 65
Distribution of Code
Code divided in 3 parts
server:
all classes required for server program
download:
all classes eventually needed by client and possibly dynamically loaded by client
including all dependent classes, e.g., base classes, interfaces
client:
classes to run the client
the policy file (e.g., client.policy)
3 parts deployed then :
server:
computer running server application
download:
download folder of Web server
client:
computer running client application
SYSTEM SOFTWARE 66
RMI
Motivation
Architecture
Implementation of Remote Objects
Parameter Passing
Callbacks
RMI and Threads
Distributed Garbage Collection
Distribution and Class Loading
Literature
SYSTEM SOFTWARE 67
Literature
Horstmann, Cornell, Core Java 2, Volume II . Advance Features, Sun Microsystems,
2008: Chapter 5
Krüger, Handbuch der Java-Programmierung, 3. Auflage, Addison-Wesley, 2003,
http://www.javabuch.de: Kapitel 46
Fundamentals of RMI, Short Course,
http://java.sun.com/developer/onlineTraining/rmi/
Top Related