Java. RMI - p. 1 C.Bac Java Remote Method Invocation Christian Bac Original Olivier Dedieu
Java. RMI - p. 2 C.Bac RMI en résumé Permet de faire interagir des objets –Situés dans des espaces d'adressage distincts –Potentiellement situés sur des machines distinctes Repose sur les classes de sérialisation (mécanisme de base pour stocker et transmettre des données complexes en java) Simple à mettre en œuvre (voir exemple) : –Définir l'interface de l'objet distribué (OD) –Côté serveur : implémenter l'OD et l'attacher à une URL –Côté serveur : générer les stubs et skeletons (rmic) et diffuser l'OD –Côté client : s'associer à l'OD (URL) et l'invoquer Manipulation d'un OD tout autre objet Java
Java. RMI - p. 3 C.Bac RMI vs. CORBA -RMI est propriétaire SUN / CORBA est une norme -RMI est moins ambitieux mais plus simple à mettre en œuvre -RMI n'offre pas d'interopérabilité avec d'autres langages -RMI est beaucoup plus lent que les implémentations de CORBA +RMI propose une implémentation standard +RMI est disponible dans toute architecture java +RMI est object-oriented / CORBA est object-based +IDL natif du langage interface de l'objet distribué (OD) +Les OD se manipulent comme les Objets Locaux (grâce au DGC) +RMI supporte le passage d'objets locaux par copie +RMI intègre une gestion de la sécurité (RMISecurityManager, ACL,...)
Java. RMI - p. 4 C.Bac Références Tutoriel simple : Tutoriel Sun plus complet : x.htmlhttp://java.sun.com/docs/books/tutorial/rmi/inde x.html Spécifications pour lever les doutes : /rmiTOC.htmlhttp://java.sun.com/j2se/1.3/docs/guide/rmi/spec /rmiTOC.html
Java. RMI - p. 5 C.Bac Architecture (1)
Java. RMI - p. 6 C.Bac Architecture (2) JVM Client Banque_stub { ajouter(int) retirer(int) Etat etat(Date) } Banque_skel Banque { ajouter(int) retirer(int) Etat etat(Date) } TCP/I P rmiregistry Naming (RMI) (1099) JVM 1 (RMI)
Java. RMI - p. 7 C.Bac Architecture (3) JVM Client Banque_stub { ajouter(int) retirer(int) Etat etat(Date) } Banque_skel Banque { ajouter(int) retirer(int) Etat etat(Date) } HTT P HTTPD javarmi.cgi Tunneling HTTP cgi
Java. RMI - p. 8 C.Bac Distributed Garbage Collector (DGC) DGC interagit avec les GC locaux et utilise un mécanisme de compteur de référence réparti Lorsqu'un OD est passé en paramètre à un autre OD ref_count++ Lorsqu'un stub n'est plus référencé weak reference Lorsque le GC du client libère le stub, sa méthode finalize est appellée et informe le DGC ref_count-- Lorsque le nombre de références d'un OD = 0 weak reference Le GC du serveur peut alors libérer l'OD Le client doit régulièrement renouveler son bail auprès du DGC. Si référence à un OD libérée RemoteException
Java. RMI - p. 9 C.Bac Exemple : interface de l'OD public interface Banque extends java.rmi.Remote { public void ajouter(String id, double somme) throws java.rmi.RemoteException; public void retirer(String id, double somme) throws java.rmi.RemoteException; public Position position(String id) throws java.rmi.RemoteException; } // Tous les objets en paramètre ou en retour de fonction // doivent être sérialisables
Java. RMI - p. 10 C.Bac Implémentation de l'OD public class BanqueImpl extends java.rmi.server.UnicastRemoteObject implements Banque { Hashtable clients; public BanqueImpl(Hashtable clients) throws java.rmi.RemoteException { super(); this.clients = clients;} public void ajouter(String id, double somme) throws java.rmi.RemoteException { clients.get(id).ajouter(somme); } public void retirer(String id, double somme) throws java.rmi.RemoteException { clients.get(id).retirer(somme); } public Position position(String id) throws java.rmi.RemoteException { return (clients.get(id).position(); } }
Java. RMI - p. 11 C.Bac Classe retournée par l'OD import java.util.Date; public class Position implements java.io.Serializable { private static final long serialVersionUID = L; private double solde; private Date dateDerniereOperation; public Position(double solde) { this.solde = solde; this.dateDerniereOperation = new Date();} public void ajouter(double somme) { solde += somme; dateDerniereOperation = new Date(); } public void retirer(double somme) { solde -= somme; dateDerniereOperation = new Date(); } public double get_solde(){ return solde; } public Date get_dateDerniereOp(){ return dateDerniereOperation; } }
Java. RMI - p. 12 C.Bac Classe interne à l'OD class Compte { private String reference, Position position; Compte(String reference, double solde) { this.reference = reference; position = new Position(solde); } void ajouter(double somme) { position.ajouter(somme); } void retirer(double somme) { position.retirer(somme); } Position position() { return position; } String get_reference(){ return reference; } }
Java. RMI - p. 13 C.Bac Enregistrer une instance de l'OD import java.util.Hashtable; public class BanqueServeur { public static void main(String[] args) { Hashtable clients = initComptesClients(); try { BanqueImpl obj = new BanqueImpl(clients); java.rmi.Naming.rebind("MaBanque", obj); System.out.println("Objet distribue 'MaBanque' est enregistre"); } catch(Exception e) { e.printStackTrace(); }...
Java. RMI - p. 14 C.Bac Instance de l'OD suite... private static Hashtable initComptesClients(){ // These accounts should be read from file or database Hashtable clients = new Hashtable (); Compte arg1 = new Compte("12345", 5000); clients.put("12345", arg1); return clients; }
Java. RMI - p. 15 C.Bac Commandes Compiler les sources j avac Position.java Compte.java Banque.java BanqueImpl.java \ BanqueServeur.java Générer les stub et les skeletons rmic banque.BanqueImpl -> BanqueImpl_Stub.class et BanqueImpl_Skel.class Lancer le RMI registry rmiregistry & Lancer l'OD java banque.BanqueImpl & java -Djava.rmi.server.codebase= \ banque.BanqueImplhttp://falconet.inria/codebase
Java. RMI - p. 16 C.Bac Programme client public class Client { public static void main(String[] args) { try { Banque b = (Banque)java.rmi.Naming.lookup("MaBanque"); b.ajouter(args[0], ); b.retirer(args[0], 20.00); Position p = b.position(args[0]); System.out.println("Position au "+p.dateDerniereOperation+":"+ p.solde); } catch(Exception e) { e.printStackTrace(); }