Download presentation
Presentation is loading. Please wait.
1
Multi-Dispatch in the Java VM
Multi-Dispatch in the JavaTM Virtual Machine: Design and Implementation Computing Science Computer Science University of Alberta The University of Western Ontario Chris Dutchyn Paul Lu Duane Szafron Steve Bromling Wade Holst 8 November 2018 Multi-Dispatch in the Java VM
2
Multi-Dispatch in the Java VM
Recognize this code? class Component ... { void processEvent(AWTEvent e) { if (e instanceof FocusEvent) processEvent((FocusEvent e)); else if (e instanceof MouseEvent) { switch (e.getID()) { case MouseEvent.MOUSE_PRESSED: case MouseEvent.MOUSE_EXITED: processEvent((MouseEvent e)); break; case MouseEvent.MOUSE_DRAGGED: case MouseEvent.MOUSE_MOVED: processEvent((MouseMotionEvent e)); ...} } else if (e instanceof KeyEvent) processEvent((KeyEvent e)); } else if (e instanceof ...)) ...} } We write this sort of code constantly: We need to specialize on a given Component such as Button, Scrollbar, TextBox, etc. But we need different responses to various kinds of Events. So, we choose a dominant decomposition such as component, and write our own dispatcher to select on the types of the other arguments. This dispatch routine suffers from many difficulties: * it’s complicated - containing many conditionals - suffers from subtle order dependencies * it’s difficult to extend - adding another event type requires source changes here - or another layer of method invocations if you lack source This is a simplified version of the heart of Sun’s AWT - but we write this sort of program in many places. 8 November 2018 Multi-Dispatch in the Java VM
3
Multi-Argument Dispatch
Graphical User Interfaces especially Drag & Drop, Cut & Paste Printing result depends on printer capabilities and document type Binary methods key example is equality testing: Comparable 8 November 2018 Multi-Dispatch in the Java VM
4
Multi-Dispatch in the Java VM
Multiple Dispatch Method selection based on multiple arguments It can be implemented as a sequence of dispatches on one argument each of these is a uni-dispatch a single operation applying all arguments this is a multi-dispatch Need to define dispatch - presumably everyone has an intuition so saying it should be enough. DISPATCH = method selection based on argument type. 8 November 2018 Multi-Dispatch in the Java VM
5
Multi-Dispatch in the Java VM
Overview How does Multi-Dispatch work in the JVM? Modify JVM without changing Java language Multi-dispatching at a callsite Denoting multi-dispatchable methods How fast is it? Event Dispatch Multi-Swing Time permitting, we will go into future work. We will look.at issues that arose from the experience as well. 8 November 2018 Multi-Dispatch in the Java VM
6
Anatomy of Java Dispatch
Java Source … Component c = new Button; AWTEvent e = new FocusEvent; c.processEvent(e); Java Binary 1 CLASS “Component” 2 NAME&TYPE “processEvent” “(LAWTEvent;)V” 3 METHOD #1, #2 … apush c apush e invokevirtual #3 For simplicity, we’ve shown the strings as contained in the CLASS and other elements; in fact they are stored as separate constant-pool indexes. 8 November 2018 Multi-Dispatch in the Java VM
7
Method Overloading = Static Multi-Dispatch
javac selects from the method dictionary of the receiver’s static class the method that is most specific applicable to the declared types of the arguments class Component … { void processEvent(AWTEvent e) { … } void processEvent(FocusEvent f) void processEvent(KeyEvent k) … } I’m using javac as the name of the Java compiler because it’s the well-known name, but there’s not implied vendor-dependency. STATIC TYPE = declared type. DYNAMIC TYPE = execution time type - in C++ this would be determined using RTTI or dynamic casts. Note that this means that Java already recognizes the problem of ambiguous method declarations. It aborts the compile with an ambiguous method error in the case of class A { void m(B b) { … } } class B extends A { void m(A a) { … } } class Main { public static void main(String args[]) { B b = new B; b.m(b); } } 8 November 2018 Multi-Dispatch in the Java VM
8
Method Overriding = Dynamic Uni-Dispatch
JVM selects from the list of methods understood by the receiving object’s class the method that lexically matches the name & type signature 1 CLASS “Button” 2 NAME&TYPE “processEvent” “(LAWTEvent;)V” 3 METHOD #1, #2 4 NAME&TYPE “processEvent” “(LFocusEvent;)V” 5 METHOD #1, #4 6 NAME&TYPE “processEvent” “(LKeyEvent;)V” 7 METHOD #1, #6 I’m using javac as the name of the Java compiler because it’s the well-known name, but there’s not implied vendor-dependency. STATIC TYPE = declared type. DYNAMIC TYPE = execution time type - in C++ this would be determined using RTTI or dynamic casts. Note: at this point we’re finished our review of Java dispatch and we need to transition into the Multi-Dispatch. 8 November 2018 Multi-Dispatch in the Java VM
9
Multi-Dispatch in the Java VM
Invoking the Method The JVM must allocate a new operand stack and prepare to execute the bytecode for the method in the Sun classic VM, this process is performed by calling an invoker subroutine that is specialized on a method-by-method basis for the number and kind of arguments Dispatch is complete in this case, into a method that checks the event type, and dispatches again 8 November 2018 Multi-Dispatch in the Java VM
10
Multi-Dispatch in the Java VM
At a Callsite The signature describes the formal parameters the number, type, and size The operand stack holds the matching arguments 1 CLASS “Button” 2 NAME&TYPE “processEvent” “(LAWTEvent;)V” 3 METHOD #1, #2 4 NAME&TYPE “processEvent” “(LFocusEvent;)V” 5 METHOD #1, #4 6 NAME&TYPE “processEvent” “(LKeyEvent;)V” 7 METHOD #1, #6 Let’s step back a moment … at the callsite, we know: 0) the method selector 1) the actual arguments and therefore the types of each argument 2) detailed information about all methods understood by the receiver name and parameter types So, we could more precisely target the dispatch to the method that most precisely matches the argument types Note: This typically doesn’t work in C++ because: 1) without RTTI you don’t have the types of the arguments 2) the method selector is usually compiled out - remaining only as virtual function table index 3) the number of arguments is compiled out too 4) the virtual function table contains no information about method selector and parameter types apush c (Button) apush e (FocusEvent) 8 November 2018 Multi-Dispatch in the Java VM
11
Multi-Dispatch a Callsite
More precise information about argument types More precise method with same arity can be selected by a replacement invoker we call the multi-invoker 1 CLASS “Button” 2 NAME&TYPE “processEvent” “(LAWTEvent;)V” 3 METHOD #1, #2 4 NAME&TYPE “processEvent” “(LFocusEvent;)V” 5 METHOD #1, #4 6 NAME&TYPE “processEvent” “(LKeyEvent;)V” 7 METHOD #1, #6 Let’s step back a moment … at the callsite, we know: 0) the method selector 1) the actual arguments and therefore the types of each argument 2) detailed information about all methods understood by the receiver name and parameter types So, we could more precisely target the dispatch to the method that most precisely matches the argument types Note: This typically doesn’t work in C++ because: 1) without RTTI you don’t have the types of the arguments 2) the method selector is usually compiled out - remaining only as virtual function table index 3) the number of arguments is compiled out too 4) the virtual function table contains no information about method selector and parameter types apush c (Button) apush e (FocusEvent) 8 November 2018 Multi-Dispatch in the Java VM
12
Multi-Dispatch Compatibility
We select the most-specific applicable method that matches the original method: the same number of arguments each multimethod parameter has the same type as (or be a subtype of) the corresponding argument We also verify that the method return type is the same as (or a subtype of) the overridden method otherwise we throw IllegalReturnTypeChange Further notes from previous page: We have an MSA algorithm that implements a dynamic version of the MSA algorithm used by the java compiler to perform static multi-dispatch. This algorithm is given in the Java Language Specification by Gosling et al. We use it as a reference platform to ensure compatibility of multi-dispatch with the static multi-dispatch. We also have a table-based dispatcher based developed at the University of Alberta. It is described in a technical report (cited in our conference paper) and has been accepted to Software Practice and Experience. My extensions to deal with null types and incomplete parameter type information may be included there. Why throw an error: Multi-dispatch Java should never throw these, because it shouldn’t compile. But, the JVM must preserve its own security, so we must check and signal errors ourselves. 8 November 2018 Multi-Dispatch in the Java VM
13
Denoting Multi-Dispatch
Implement interface MultiDispatchable signals that all method calls to objects of this class (and subclass) are multi-dispatched eliminates user-written dispatch code Do not install multi-invoker when inappropriate class Button extends Component implements MultiDispatchable { … void processEvent(AWTEvent e) { /*** code removed ***/ } void processEvent(FocusEvent f) { /* unchanged */ } void processEvent(MouseEvent f) { void processEvent(KeyEvent k) { void setX(int x) { … } … } We have a growing list of situations where the multi-invoker is not required * non-object argument types * private or final without multimethod overrides * private or final where dynamic type is known precisely 8 November 2018 Multi-Dispatch in the Java VM
14
Multi-Dispatch in the Java VM
Java Syntax Unchanged Using an empty interface is not novel Cloneable operates in the same way Unlike other efforts, we neither extend the language syntax nor modify the compiler we use an unchanged javac to compile tests We can extend existing libraries to support multi-dispatch without source and without additional layers of dispatch W.R.T. the last point, we do require the user to supply a new class definition in order to include the multi-dispatch interface Removing this restriction is the “TRACES” problem investigated by Gregor Kiczales a few years ago. His solution - ASPECTS - and current AspectJ is compatible with our virtual machine. 8 November 2018 Multi-Dispatch in the Java VM
15
Multi-Dispatch in the Java VM
Performance Results The paper includes additional tests showing compatibility with uni-dispatch, no performance degradation, etc. We give selected results for our tuned, table-based dispatcher. 8 November 2018 Multi-Dispatch in the Java VM
16
Multi-Dispatch in the Java VM
Event Dispatch Dispatch processEvent() across seven event types seven components VMs: JVM = classic VM mJVM = multi-JVM with table-based dispatcher The paper includes more benchmarks: javac - compatibility and performance simple multi-dispatch - simple double dispatch The spreadsheet underlying the chart includes the MSA numbers. 8 November 2018 Multi-Dispatch in the Java VM
17
Multi-Dispatch in the Java VM
Multi-Swing (and AWT) Modified 92 of 846 classes (11%) Replaced 171 conditionals (5%) Mean number of decision points reduced from 3.8 to 2.0 per method Added 57 new event subclasses Added 123 new multimethods Working with this real-world application reinforced 1) some of the issues regarding null parameters, return types, visibility, and type promotion. 8 November 2018 Multi-Dispatch in the Java VM
18
Multi-Dispatch in the Java VM
Multi-Swing Results The multi-dispatch version executes about 8% fewer dispatches and the multi-dispatches represent approximately 7.7% of the dispatches. These are interpreter-only numbers, OpenJIT isn’t robust enough yet :-( Also, we didn’t see dramatic improvements because we couldn’t disable locking - Swing demand-loads classes by attempting to invoke methods in non-existent classes and catching the resulting (class-not-found and null-pointer) exceptions. This means that we could not guarantee that classes were loaded in advance of any multi-dispatch. One other reason for no dramatic improvement in performance is that dispatch occasionally was ternary or higher! For instance, we saw invocations such as aComponent.add(anotherComponent, …, anObject) where the selection depended on the two components, and whether anObject was a single item or an array of items. But, the code only needed to test for anotherComponent, because that forced the anObject type. The arity ranged up to 10+, with dispatch varying on 3+ arguments. Also, because we needed to add subclass links that slowed the JVM marginally for single-dispatch because of added memory usage. 8 November 2018 Multi-Dispatch in the Java VM
19
Multi-Dispatch in the Java VM
Summary Added dynamic multi-dispatch to Java without changing syntax or compiler, allowing programmer to select classes supporting multi-dispatch, without penalizing existing uni-dispatch, and maintaining reflection and existing APIs. Provide initial performance results table-based dispatcher surpasses interpreter table-based dispatcher approach JIT. As it turns out, we exceed interpreted hand-coded custom dispatchers that use the fastest access (fields), fastest type numbering (integers) and the fastest second dispatch (none - inlined)! And, we’re within a factor of 3 for the best JIT compilers of the same highest-performance code. 8 November 2018 Multi-Dispatch in the Java VM
20
Multi-Dispatch in the Java VM
Future Work Compare with other dispatchers Optimize OpenJIT support Test multi-dispatch during class-load Support table reduction when unloading classes Investigate language extensions to allow fine-grained multi-dispatch One example of where JIT inlining is possible, but not supported occurs when no overriding private or final methods exist. 8 November 2018 Multi-Dispatch in the Java VM
21
Multi-Dispatch in the Java VM
Questions? What about: 1. Exceptions:the JLS specifies that overriding methods must throw a subset of the exceptions that the original method throws. The JVMS does not specify that this must hold for .class files. But, static typechecking is valuable, so our code-checking tool declares it a warning. 2. Visibility modifiers: the JLS specifies that overriding methods must have equal or greater visibility. The JVMS does not specify that this must hold for .class files. Again static typechecking is valuable, so our separate code-checking tool flags these as warnings. 3. Reflection: java.lang.reflect.Method.apply(java.lang.Object[]) calls the method invoker, so it multi-dispatches - offering the same semantics as writing the original code. 4. Super - only the uni-dispatch receiver can be affected by a super - how to allow super on any combination of arguments is unclear. 5. Constructors are not multi-dispatched: we cannot not decide whether a constructor invocation should be statically dispatched or dynamically dispatched - they are coded the same way, but among A) a constructor in the same class with a less specialized argument, B) a super-constructor with the same argument, and C) a super-constructor with a less specialized argument. These are all possible, and coded the same way. 8 November 2018 Multi-Dispatch in the Java VM
22
Supplemental Material
Source Availability Double Dispatch Comparisons Supported Invoke Bytecodes Alternate Denotation 8 November 2018 Multi-Dispatch in the Java VM
23
Multi-Dispatch in the Java VM
Source Availability We’re packaging it up we expect to have it available in a couple of weeks. But ... We use the Sun classic VM under the research provisions of their Community Source License. Hence, you must agree to that same license; And we need to ensure that you accept that license, so only requests accepted. 8 November 2018 Multi-Dispatch in the Java VM
24
Double Dispatch Compared
8 November 2018 Multi-Dispatch in the Java VM
25
Supported Invoke Bytecodes
Invokevirtual VirtualMultiDispatchable invokevirtual_quick / wide invokenonvirtual invokestatic StaticMultiDispatchable invokestatic_quick / wide invokespecial SpecialMultiDispatchable invokespecial_quick / wide invokeinterface - no interface defined because invoker routines already redefined We can’t support constructors because of class X { … } class Y extends X { … } class A { A(X x) { … } A(Y y) { this.A((X) x); … } } becomes an infinite loop. 8 November 2018 Multi-Dispatch in the Java VM
26
Multi-Dispatch in the Java VM
Static Checking MDLint - a code-testing tool that checks binary files for the previous error and for: overriding throws clauses are a subset of overridden method overriding method has equal or greater visibility note that visibility security checks are still in effect Lapses in these are Java errors not JVM errors Also warns about argument combinations that lead to ambiguous multi-dispatches only when encountered does the multi-JVM throw AmbiguousMethodException 8 November 2018 Multi-Dispatch in the Java VM
27
Multi-Dispatch in the Java VM
OpenJIT Support Callsites compile to an invoker that dispatches the target method from a virtual function table For multimethods we replace the virtual function table target to a routine which selects a more precise multimethod jumps to the actual compiled code It calls the same multimethod dispatcher that operates in the interpreter 8 November 2018 Multi-Dispatch in the Java VM
28
Multi-Dispatch and OpenJIT
Disabled inlining of private and final methods because they may still be dispatched based on arguments: class LoggingButton extends Button { void processEvent(AWTEvent e) { this.logEvent(e); super.processEvent(e); } private void logEvent(FocusEvent f) { … } private void logEvent(MouseEvent m) { … } … } 8 November 2018 Multi-Dispatch in the Java VM
29
Multi-Dispatch in the Java VM
The Visitor Pattern The need for method selection based on the dynamic type of more than one argument is so strong that OOPSLA included a 3-page paper in their first conference describing double dispatch, already a well-known technique at that time Since then GoF raised this technique to the level of a design pattern 8 November 2018 Multi-Dispatch in the Java VM
30
Do we need dynamic multiple dispatch? Multi-Dispatch in the Java VM
The Key Question Do we need dynamic multiple dispatch? How do we implement it? Multi-Dispatch in the Java VM 8 November 2018 Multi-Dispatch in the Java VM
31
Multi-Dispatch in the Java VM
Alternate Denotation The mJVM only applies the empty interface at class load time if we “leaked” the method-by-method flag out into the .class file, then we could provide method-granularity multi-dispatch but any method that was eligible as an overriding multimethod would be multi-dispatched as well What should the language notation be? 8 November 2018 Multi-Dispatch in the Java VM
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.