RMI = Remote Method Invocation Tato technologie využívá vzdálené objekty tím, že volá jejich metody. Argumenty metod jsou požadavky a metoda případně vrátí výsledek. Vzdálený objekt existuje v jiné JVM - povětšinou na jiném počítači. Klient komunikuje se vzdáleným objektem pouze přes interfejs, který: musí být potomkem interfejsu Remote všechny jeho metody throws RemoteException Vlastní vzdálený objekt, tj. implementace, musí být: realizací programátorem definovaného interfejsu potomkem třídy - java.rmi.server.UnicastRemoteObject či Activatable ( ta zařídí export ) - anebo musí být explicitně exportován metodou java.rmi.server.UnicastRemoteObject.export(...). PJV14
RRL = Remote Reference Layer Klient - Server Vývojář odpovídá pouze za definice interfejsů a implementujících tříd - nemusí se starat o komunikační protokol. Původně musel zajistit generaci stubu a sketetonu pomocí dodatečného kompilátoru rmic – od verze 1.5 se tyto vytvářejí automaticky. JVM JVM Java RMI client (application layer) Java RMI server (application layer) stub skeleton socket factory RRL RRL Transport layer Transport layer socket JRMP on TCP/IP RRL = Remote Reference Layer PJV14
Pro v1.2 je skeleton integrován v UnicastRemoteObject RMI Unicast RemoteObject Security Manager Remote MojeTrida MujInterfejs registry Registry stub rmic client server new program object skel eton MujInterfejs stub RMI / IIOP Pro v1.2 je skeleton integrován v UnicastRemoteObject PJV14
Spouštění RMI Server vytvoří jeden vzdálený objekt a předá serializovaný stub do registry k registraci. Ten realizuje výpočet i pro více klientů. Klient získá od registry handle ke vzdálenému objektu. Registry mu vrátí serializovanou kopii stubu. Klient z ní vytvoří instanci stubu. Pro další komunikaci klient-server není registry nutná. Klientský program zavolá nějakou metodu stubu. Stub kontaktuje skeleton v serveru. Skeleton zavolá metodu vzdáleného objektu. Při každém zavolání vytvoří server nové vlákno, které provede výpočet v metodě. Metoda vrátí výsledek skeletonu. Skeleton vrátí výsledek stubu. Stub vrátí výsledek klientskému programu. PJV14
ActivationInstantiator java.rmi.* javax.management.remote.rmi RMIServer Impl RMIIIOP ServerImpl Remote RMIServer ( tag interface ) RMIJRMP ServerImpl java.rmi.registry Locate Registry Registry Distributed Garbage Collection java.rmi.dgc Marshalled Object Lease VMID DGC Naming java.rmi.activation ActivationInstantiator Activation Desc Activation GroupDesc java.lang ActivationMonitor Security Manager ActivationSystem Activation ID Activation GroupID RMISecurity Manager Activator PJV14
ActivationInstantiator RMIClientSocketFactory RMIServerSocketFactory java.rmi.server tag interface java.rmi Remote Object Remote java.io Externalizable javax.rmi.CORBA.Stub java.rmi.activation Remote Stub Remote Server Activable _Remote_Stub RemoteRef ServerRef Unreferenced Unicast RemoteObject RMIClass LoaderSpi RMIConnection Impl java.rmi.activation Activation Group RMIConnection Impl_Stub RMIClass Loader UID RMIServer Activation Group_Stub ActivationInstantiator javax.management.remote.rmi java.rmi.activation java.rmi.activation ObjID RMISocket Factory Portable RemoteObject RMIClientSocketFactory RMIServerSocketFactory RMIFailureHandler PJV14
interfejs java.rmi.Registry public void bind( String name, Remote obj ) throws RemoteException, AlreadyBoundException, AccessException public void unbind( String name ) throws RemoteException, NotBoundException, AccessException public void rebind( String name, Remote obj ) throws RemoteException, AccessException public String[ ] list( ) throws RemoteException, AccessException public Remote lookup( String name ) throws RemoteException, PJV14
Registry čili registratura umožňuje evidovat vzdálené objekty pod jednoduchým jménem. Klient jejím prostřednictvím může navázat spojení se serverem. Registry není perzistentní. Může být spuštěna v rámci OS nebo JVM. Každý servrový proces může udržovat vlastní registry nebo sdílet jedinou podporující všechny virtuální stroje na lokálním systému. Registry se vytvoří zavoláním rmiregistry.exec [ port | 1099 ], z adresáře classes anebo se tam zkopíruje jdk/bin. ( Ve Windows je třeba zkopírovat také jli.dll, tj. application extension. ) Registry se ovládá statickými metodami třídy java.rmi.Naming: bind, unbind, rebind, list a lookup PJV14
Použití Registry reg = LocateRegistry.createRegistry( port ); //SINGLETON reg.bind( "Moje", new MojeTrida( ) ); Spuštění zevnitř: Runtime.getRuntime( ).exec( "rmiregistry" ); Runtime.getRuntime( ).exec( "rmid –J-Djava.security.policy=rmid.policy" ); javaw – background in Win PJV14
Využití RMI Naming Service Klient vyhledá vzdálený objekt jménem takto: rmi://host:port/name v metodě Naming.lookup. ( Defaultně: rmi localhost 1099 .) Např.: String id = "rmi://" + host + ":" + port + "/Moje" ; MujInterfejs z = ( MujInterfejs ) Naming.lookup(); z.metoda1( ... ); PJV14
java.rmi.MarshalledObject Po deserializaci instance MarshalledObject není její obsah deserializován. Obsahuje totiž pole bytů, které může být později interpretováno jako objekt. Codebase URL je uložen uvnitř této struktury a ukazuje kde jsou příslušné classy uloženy pro automatické stažení. Tedy lze deserializovat na strojích nemající patřičnou třídu v classpath. Objekty mohou být předávány přes více strojů aniž jsou plně deserializovány. ArrayList data = ... MarshalledObject mo = new MarshalledObject( data ); Object o = mo.get( ); PJV14
Dřívější příprava stubu a skeletonu Pro uskutečnění spojení mezi klientem a serverem je třeba na straně klienta vytvoří tzv. stub. ( V Javě 1.1 bylo nutné ještě na straně serveru vytvářet tzv. skeleton. ) To zařizuje speciální kompilátor rmic, který se nalézá v j2sdk/bin/... Stub vytváří rmic podle třídy vzdáleného objektu. V JBuilderu je proto nutno u těchto tříd zvolit: -> Properties Generate RMI stub/skeleton Options: -keep –v1.2 Při rebuild se v patřičném podadresáři balíčku v classes\...\ vytvoří MojeTrida_Stub.class a v adresáři classes\Generated Source\...\MojeTrida_Stub.java. PJV14
Aktivace objektů Aktivatabilní objekty jsou zpravidla vedeny na separátní(ch) JVM. Tyto JVM se definují jako Activation Group - v ní je Activation Monitor, který sleduje všechny příslušné objektu a i tu grupu. Objekty i grupy mají ID a deskriptor. Activation group ActivationGroupID ActivationGroupDesc Activation Monitor Activatable object ActivationID ActivationDesc PJV14
Aktivační grupy Aktivátor vytváří aktivační grupy. Tím je RMI démon v jdk/bin/rmid.exe Aktivační grupy se vytvoří pomocí tříd z java.rmi.activation: ActivationGroupDesc gd = new ActivationGroupDesc( null, null ); ActivationGroupID gi = ActivationGroup.getSystem( ).registerGroup( gd ); ActivationGroup.createGroup( gi, de, 0 ); // 0 – na kterémkoli portu PJV14
Aktivatabilní objekty Implementace vzdáleného objektu je buď potomkem třídy Activatable ActivationGroup.create( ... ) viz výše String[ ] names = { , , }; MarshalledObject mo = new MarshalledObject( names ); ActivationDesc desc = new ActivationDesc( gID, " … ", null, mo ); Registrovat takto: RemoteObject stub = ( RemoteObject ) Activatable.register(desc); Naming.rebind( "MyRENOBject" , stub ); anebo je exportován: V konstruktoru se přijme ActivationID id a MarshalledObject mo names = ( String[ ] ) mo.get( ); Activatable.export( this, id, 0 ); // export do RMIRegistry Tyto úpravy se týkají pouze serveru. Pro klienta je to transparentní. PJV14