Multitasking JVMs Isolates and KaffeOS Presentation by James Rose Multitasking in Java We want to share the virtual machine Share bytecode Share JIT-compiled native code Start JVM once Efficient IPC Naïve approach Create a thread for each task Hope for the best! Problems with Sharing No way to enforce separation No accounting for resources No way to safely terminate processes Approaches Code-to-code Modified translation JVM Approach taken by Kaffe, MVM Sharing in KaffeOS Per-process heap and namespace Shared heaps for communication between processes Common shared.* namespace for all shared objects KaffeOS Memory Structure No pointers to user heaps except from kernel Separation in KaffeOS Write barrier prevents illegal references Shared code can’t keep user objects alive All heaps have independent GC Cross-heap references tracked by reference counting Termination in KaffeOS User/kernel separation allows safe termination Termination deferred inside kernel code Shared objects are always on top of call stack: malicious code can be terminated without harm to system Accounting in KaffeOS Memory accounting includes allocations within the VM for a process Independent GC improves accuracy Shared heaps charged to all sharers Precise resource accounting prevents denial-of-service attacks JSR-121: Isolates and MVM Defines Isolate class Defines a simple mechanism for passing messages MVM: HotSpot + JSR-121 MVM is not an OS No resource accounting Cross-Isolate Method Invocation Or XIMI, for short Stripped-down version of RMI Isolates can call methods on stubs of objects in other Isolates Stubs are generated by the VM dynamically (no rmic) Portals XIMI equivalent of RMI’s RemoteObject Objects are wrapped in Portals and passed to clients public abstract class Portal { static public Portal newPortal( Class interface, Object target, boolean copyable); //... } Invoking Methods on Portals A method call spawns a new thread in the server… Or blocks until the server calls accept() Arguments to the method are “serialized” Not really, that’s slow Method calls may fail if server dies What happens then? Heap Structure Generational GC: Shared old generation, per-isolate new generation XIReference: weak reference held only by stubs Heap Structure XIReference old space new spaces Isolate A XIMIStub$Map Map nameserv Isolate B HashMap Portal KaffeOS Write barriers enforce isolation on shared objects Methods invoked directly Write barriers slow down all programs MVM Objects or stubs are copied between isolates Methods execute in the owning isolate Resource accounting tricky Applications Java shell Java daemon Dynamic web server Web browser Which model fits these applications better? Web Server Natural way to code it: interface WebRequest { String getPath(); String getHostname(); String getHTTPVersion(); void println (String out); } interface Servlet { void run (WebRequest w); } WebServer in KaffeOS WebRequest must be in shared.* But now WebRequest can’t do anything with WebServer! The paper does not define a communication mechanism, only a sharing mechanism WebServer in MVM/XIMI class WebServer { public void answerQuery(Socket s) { // ..make WebRequest object.. port = Portal.newPortal( WebRequest, curRequest, false); new Isolate(appletName).start (port); } } XIMI WebServer Execution applet server get print get print This is stupid… Switching contexts like this is silly and slow But a coarse-grained interface is inconvenient for many applications RMI makes more sense between machines than within machines MVM Structure XIMI Heap Isolate 1 Heap Shared Code Isolate 2