Koordinierung – ConcurrentModificationException (1) • Beispielprogramm funktioniert nicht immer AVO-Übung 2 1 2 Java Remote Method Invocation (RMI) 3 4 5 Andreas I. Schmied ([email protected]) WARNING Coordination needed: Person 2 wants to work while Person 1 active. [avo1.Calendar.getEntriesForPerson] Exception in thread ”Thread of Client 1” java.util.ConcurrentModificationException at java.util.HashMap$KeyIterator.next(HashMap.java:823) at avo1.Calendar.getEntriesForPerson(Calendar.java:36) • Calendar-Attribut 1 AspectIX-Team Abteilung Verteilte Systeme Universität Ulm private Set<Entry> entries = new HashSet<Entry>(); • Calendar.getEntryCount/getRandomEntry() 1 for (Entry e: entries) { ... } • Erzeugt intern Iterator-Objekt WS2005 • Calendar.removeEntry(Entry e) 1 entries.remove(e); ➜ Iterator vs. Modifikator [email protected] Koordinierung – ConcurrentModificationException (2) AVO-Übung 2 (WS2005) 1 Basics – Änderungen am Code • Einfacher Ausweg? • Gegenseitiger Ausschluss im Client (gekürzt) 1 2 3 • Code aus avo1 wiederverwenden synchronized(calendar) { Entry entry = calendar.getRandomEntry(person); } • Calendar soll Remote-Objekt werden 4 5 6 7 • implementiert Remote-Interface • erbt/benutzt UnicastRemoteObject synchronized(calendar) { calendar.removeEntry(person, entry); } • Person/Entry by-Copy serialisiert übertragen • Prozess-globales Objekt calendar“ zur Koordinierung • implementieren java.io.Serializable ” • Achtung: Beispiel zur Demonstration eines Effekts ➜ Normalerweise Koordinierung innerhalb Calendar ➜ Koordinierung pro Methode/Statement [email protected] AVO-Übung 2 (WS2005) 2 [email protected] AVO-Übung 2 (WS2005) 3 Basics – Programmstarts Basics – Sicherheit • Client • Security Manager • Zugriff auf initiales Remote-Objekt • Über Naming Service 1 • Policies steuern Verhalten • Server • geprüft in java.lang/net-Code von Sun • Codebase mit System.setProperties() bzw. VM Property setzen 1 System.setSecurityManager(new java.rmi.RMISecurityManager()); • notwendig zum Class Loading • Ebenfalls Remote-Objekt • Referenz auf Naming Service? • Policy File mit Rechten java −Djava.rmi.server.codebase=<URL> • Classpath muss mit Slash beendet werden! • java.net.InetAddress.getLocalHost().getHostName() 1 java −Djava.security.policy=<FILE> 1 grant { //permission java.security.AllPermission; permission java.net.SocketPermission ”localhost:1099”, ”connect, resolve, accept”; }; 2 • Multi-Host/-Net Szenarien testen 3 4 • Firewalls berücksichtigen 5 • Security-Manager setzen... [email protected] AVO-Übung 2 (WS2005) 4 Basics – RMI-Registry [email protected] AVO-Übung 2 (WS2005) 5 Semantik – Portierung • Lokales Programm einfach mit Remoting erweiterbar? • Code aus avo1 wiederverwenden • Darf keinen direkten Zugriff auf Classpath der Objekte haben • 1. Versuch • Codebase-Property würde eliminiert • Remote-Klasse erbt lokale Implementierung • Remote-Interface einziehen“ • Client bekäme Stub ohne Codebase-Annotation ” • Adresse localhost:1099, oder: 1 • LocateRegistry.getRegistry(String host, int port, ...) • Naming.lookup(”//rhost:rport/name”) • Problem: Signaturen inkompatibel • Methoden in Calendar ohne RemoteException • Registry im eigenen Prozess starten 1 RemoteCalendarImpl extends Calendar implements RemoteCalendar • 2. Versuch java.rmi.registry.LocateRegistry.createRegistry(port, ...); • Ausnahmen vorausschauend“ einplanen: java.lang.Exception ” • Alternativen? • Wrapper, Code-Generatoren, AOP [email protected] AVO-Übung 2 (WS2005) 6 [email protected] AVO-Übung 2 (WS2005) 7 Semantik – Änderungen (1) Semantik – Änderungen (2) • Bsp.: Objekte als Methodenparameter 1 • Semantik des lokalen Programms erhalten? 2 3 • Bsp.: Modifikation eines Objekts 4 5 1 2 class Entry implements Serializable { String text; ... } class Calendar implements Remote { Entry getEntry(...) ... } 6 7 8 1 2 3 Get Entry7 for Person1: ”Sport” Change Text to ”Meeting” Get Entry7 for Person1: ”Sport” 1 2 3 • Entry wurde zum Client kopiert • Client änderte nur lokale Kopie class Entry implements Serializable { ... } class Calendar { Set<Entry> entries = new HashSet<Entry>(); void removeEntry(Entry e) { entries.remove(e); } } class Client { public void run() { Entry e = calendar.getRandomEntry(...); calendar.removeEntry(e); } } Person1 has 10 entries. Deleting Entry7 for Person1. Person1 has 10 entries. • Entry zum Client kopiert, Kopie an Calendar.removeEntry() zurück • Entry mit neuer Objekt-ID an HashSet.remove() weitergegeben • Objekt kann nicht gefunden werden ➜ Ausweg: Entry.hashCode/equals überschreiben [email protected] AVO-Übung 2 (WS2005) 8 [email protected] AVO-Übung 2 (WS2005) 9 Activation – Aufgabe Semantik – Änderungen (3) • Calendar soll passivierbar sein • Laufzeit-Daten erhalten • Bsp.: Koordinierung im Client-Code 1 2 3 • Datenbank, hier Datei mit Serialisierung synchronized(calendar) { calendar.removeEntry(person, entry); } Realisierung • RMI-Daemon zur Reaktivierung von JVMs • genauer Ablauf? ➜ calendar ist Referenz auf Stub ➜ keine Koordinierung an Remote-Objekt, sondern an Stub • Setup-Programm • erzeugt/registriert aktivierbare Referenz auf Kalender • ohne echte Objektinstanz! • inkl. MarshalledObject • für Datenbank-Kontext, Dateipfad bei Reaktivierung • Bsp.: Locking (→Vorlesung: Reentrance) • beendet JVM sofort [email protected] AVO-Übung 2 (WS2005) 10 [email protected] AVO-Übung 2 (WS2005) 11 Activation – Setup-Abfolge (1) Activation – Änderungen im Code • RMI-Daemon rmid konfigurieren/starten • Stellt gleichzeitig RMI-Registry bereit • Benötigt weitergehende Policies • Kalenderklasse erbt von java.rmi.activation.Activatable • Alternative: Activatable.exportObject(<impl>) aufrufen • Hier unerwünscht, da Setup ohne Objektinstanz 1 2 1 2 3 4 grant { ... permission com.sun.rmi.rmid.ExecPermission ”<path to java bins>”; 3 • Zusätzlicher Konstruktor zur Reaktivierung permission com.sun.rmi.rmid.ExecOptionPermission ”−Djava.security.policy=<predefined policy file>”; 4 5 class ActvnCalendar extends Activatable ... { ... public ActvnCalendar(ActivationID id, MarshalledObject data) {...} } 6 permission com.sun.rmi.rmid.ExecOptionPermission ”−Dsun.rmi.∗”; 7 8 }; • Start-Parameter • Methoden zum Laden/Speichern des Zustands 1 • ... 2 rmid −J−Djava.security.policy=... −J−Dsun.rmi.activation.execPolicy=... • Siehe Projekt bzw. Java Guide http://java.sun.com/j2se/1.5.0/docs/tooldocs/#rmi [email protected] AVO-Übung 2 (WS2005) 12 Activation – Setup-Abfolge (2) [email protected] AVO-Übung 2 (WS2005) 13 Activation – Setup-Programm (1) • Security-Manager/Policies für Start-Programm setzen • Policies für Reaktivierung vorhalten • Setup-Programm starten 1 2 • Adresse des RMI-Daemon angeben 1 3 Properties props = new Properties(); props.put(”java.security.policy”, POLICYFILE URL); ... −Djava.rmi.activation.port=... • Deskriptor für ActivationGroup (inkl. Properties) • Client-Zugriffe 1 2 • Aktivieren ggf. Server-JVM ActivationGroupDesc.CommandEnvironment env=null; ActivationGroupDesc agd = new ActivationGroupDesc(props, env); • ActivationGroup registrieren 1 [email protected] AVO-Übung 2 (WS2005) 14 ActivationGroupID agid = ActivationGroup.getSystem().registerGroup(agd); [email protected] AVO-Übung 2 (WS2005) 15 Weitere Aspekte – Design Patterns Activation – Setup-Programm (2) • Command-Object • ActivationDescriptor für Objekt erzeugen 1 2 3 • Mehrere/komplexe Operationen abstrakt beschreiben • Serialisierbares Objekt mit Kommando-Liste • Gefahr: Nachempfinden einer Skriptsprache... MarshalledObject data = new MarshalledObject(...); ActivationDesc desc = new ActivationDesc(agid, ”avo2.ActvnCalendar”, CODEBASE URL, data); • Value-Object • Referenz erzeugen und publizieren 1 2 • • • • Calendar c = (Calendar) Activatable.register(desc); Naming.rebind(NAME, c); • Referenz wurde ohne echte Objektinstanz erzeugt! • Home/Locator/Factory-Object • Setup-JVM beenden [email protected] Daten-Attribute (zusätzlich) in Java-Bean Datenübertragung en-bloc anstatt mehrerer Getter-Aufrufe Server-Objekte selektiv exportierbar Objektattribute selektiv übertragbar • Wenige exportierte Objekte im Naming Service • Erzeugung/Auffinden weiterer Objekte AVO-Übung 2 (WS2005) 16 Weitere Aspekte – Stubs/Skeletons (1) [email protected] AVO-Übung 2 (WS2005) 17 Weitere Aspekte – Stubs/Skeletons (2) • Stub (exemplarisch, gekürzt) 1 2 3 4 5 6 7 8 9 public void deleteEntry(...) { if (useNewInvoke) { ref.invoke(this, $method deleteEntry 3, ..., −3562721982592559544L); } else { java.rmi.server.RemoteCall call = ref.newCall( (RemoteObject) this, operations, 3, interfaceHash); ref.invoke(call); ref.done(call); }} • Stubcompiler RMIC • Aufruf: rmic −vcompat −g −keep <implementation classes> • Stub und Skeleton erzeugt • Abwärtskompatibler Dispatch-Code • Dynamic Proxies • Skeleton (exemplarisch, gekürzt) 1 2 3 4 5 6 7 8 9 • • • • public void dispatch(Remote obj, RemoteCall call, int opnum, long hash) { CalendarImpl server = (CalendarImpl) obj; switch (opnum) { case 3: server.deleteEntry(...); ... break; default: throw new java.rmi.UnmarshalException(”invalid method number”); }} [email protected] AVO-Übung 2 (WS2005) 18 Implementieren beliebige Typen Generische Dispatch-Methode invoke(...) Erzeugen von Adaptern um Objektmethoden“ ” Erzeugen von Stubs/Skeletons [email protected] AVO-Übung 2 (WS2005) 19 Weitere Aspekte – Dynamic Proxies 1 Aufgabe public interface Calendar { public void deleteEntry(...); } 2 3 public class CalendarProxy implements java.lang.reflect.InvocationHandler { 4 • avo2.zip in Kürze auf dem Server public static Object newInstance(Calendar obj) { 5 6 • Code verstehen return java.lang.reflect.Proxy.newProxyInstance( obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new CalendarProxy(obj) ); 7 8 9 10 • Übungsmöglichkeiten • • • • • } 11 12 private Object obj; private CalendarProxy(Object obj) { this.obj = obj; } 13 14 15 public Object invoke(Object proxy, Method m, Object[] args) { log.fine(”invoke method ” + m.getName()); return m.invoke(obj, args); } 16 17 18 19 20 Nachprogrammieren Person ebenfalls als Remote-Objekt Aktive Clients bei Änderungen benachrichtigen Whiteboard aus Vorlesung inkl. Activation Chat: Clients und zentraler Server } [email protected] AVO-Übung 2 (WS2005) 20 [email protected] AVO-Übung 2 (WS2005) 21