Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

invokedynamic for Mere Mortals [Code One 2019]

The invokedynamic instruction (part of JSR 292) has been around since JDK7. Despite its importance to most languages that run on the JVM, many developers still do not understand how it is used or implemented. Most resources available about JSR 292 are aimed at language implementers who are experts in compiler theory and language design. This session is different, offering an overview of JSR 292 for people who are curious about how things work but do not necessarily spend all day working on java bytecode. This update of the speaker’s 2015 session on the same topic has been updated to include new uses and related changes since Java 8.

  • Be the first to comment

  • Be the first to like this

invokedynamic for Mere Mortals [Code One 2019]

  1. 1. The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation. Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events. Safe Harbor Copyright © 2019 Oracle and/or its affiliates.
  2. 2. Invokedynamic for Mere Mortals [DEV4253] Principal Member of Technical Staff Java Platform Group September 17, 2019 David Buck Copyright © 2019 Oracle and/or its affiliates.
  3. 3. JVM Sustaining Engineer OpenJDK Update Project Maintainer JavaOne Rock Star Co-author of Oracle WebLogic Server 11g 構築・運用ガイド @DavidBuckJP https://blogs.oracle.com/buck/ Who am I? David Buck (left)
  4. 4. Program Agenda Introduction java.lang.invoke invokedynamic instruction Other stuff 1 2 3 4 4
  5. 5. Introduction 5
  6. 6. Target Audience Not compiler writers Curious 6
  7. 7. Motivation Understand javap output better Understand the value JVM has as a multi-language JVM 7
  8. 8. Da Vinci Machine Project The JVM is a great platform for running all sorts of languages Great performance Portability Security (sandbox) Pre-existing libraries and frameworks 8
  9. 9. JVM-specific Scala Clojure Groovy Ceylon Fortress Gosu Kotlin Ported to JVM JRuby Jython Smalltalk Ada Scheme REXX Prolog Pascal Common LISP (a small subset of) JVM languages 9
  10. 10. Java Code Language Runtime 10 JVM OS Java Class Library JRuby Runtime JVM OS Java Class Library Ruby Code
  11. 11. non-Java language wish list Continuations Dynamic invocation Tail recursion Interface injection Other stuff 11
  12. 12. non-Java language wish list Continuations Dynamic invocation Tail recursion Interface injection Other stuff 12
  13. 13. What is dynamic typing? 13
  14. 14. What is dynamic typing? def addtwo(a, b) a + b; end 14
  15. 15. What is dynamic typing? We do not know what the types are until runtime 15
  16. 16. statically-typed vs. dynamically-typed When do we type check / link? Compilation time (javac) Runtime 16
  17. 17. Compile-time checking / linking Catch errors early Limits the type of code we can write (false positives) 17
  18. 18. Run time checking / linking Allow more freedom of programming (less false positives) Less guarantees about runtime behavior 18
  19. 19. dynamic typing != type inference object InferenceTest1 extends App { val x = 1 + 2 * 3 // the type of x is Int val y = x.toString() // the type of y is String def succ(x: Int) = x + 1 // succ returns Int values } (Shamelessly copied from http://docs.scala- lang.org/tutorials/tour/local-type-inference.html) 19
  20. 20. dynamic typing != week typing a = "40" b = a + 2 20
  21. 21. Dynamically-typed languages Allow more programs, but have to do more runtime checking. No perfect type information at compile time 21
  22. 22. Polymorphism != Dynamic typing (?!) public String bar(Object o) { return "You passed me " + o.toString(); } 22
  23. 23. The original invocation lineup invokestatic Class method invokevirtual Instance method invokeinterface Interface method Invokespecial Everything else (private, super class, constructors) 23
  24. 24. The original invocation lineup invokestatic Class method invokevirtual Instance method invokeinterface Interface method Invokespecial Everything else (private, super class, constructors) 24
  25. 25. invokestatic public class InvokeStaticExample { public static void main(String[] args) { InvokeStaticExample.foo(); } public static void foo() { System.out.println("I am foo!"); } } 25
  26. 26. The original invocation lineup invokestatic Class method invokevirtual Instance method invokeinterface Interface method Invokespecial Everything else (private, super class, constructors) 26
  27. 27. invokevirtual public class InvokeVirtualExample { public static void main(String[] args) { InvokeVirtualExample ive = new InvokeVirtualExample(); ive.foo(); } public void foo() { System.out.println("I am foo!"); } } 27
  28. 28. The original invocation lineup invokestatic Class method invokevirtual Instance method invokeinterface Interface method Invokespecial Everything else (private, super class, constructors) 28
  29. 29. public class InvokeInterfaceExample implements MyInterface { public static void main(String[] args) { MyInterface iie = new InvokeInterfaceExample(); iie.foo(); } public void foo() { System.out.println("I am foo!"); } } interface MyInterface { public void foo(); } 29 invokeinterface
  30. 30. The original invocation lineup invokestatic Class method invokevirtual Instance method invokeinterface Interface method Invokespecial Everything else (private, super class, constructors) 30
  31. 31. invokespecial public class InvokeSpecialExample { public static void main(String[] args) { InvokeSpecialExample ise = new InvokeSpecialExample(); ise.foo(); } private void foo() { System.out.println("I am foo!"); } } 31
  32. 32. Poor dynamic languages on JVM? invocation logic is not baked into the JVM like it is for Java we need to fall back on reflection 32
  33. 33. Reflection is slow security check on each invocation all arguments are Objects (boxing) 33
  34. 34. What the JVM doesn’t know can hurt it 34 Caller Reflection Magic! Callee
  35. 35. Reflection prevents inlining! 35 Caller Reflection Magic! Callee
  36. 36. No one writes code like this if (false) { // do some important stuff... System.out.println("I'm important!"); } 36
  37. 37. Or this… boolean cond = true; if (cond) { // do some important stuff... System.out.println("I'm important!"); } 37
  38. 38. public void methodB() { // ... methodA(false); // ... } public void methodA(boolean optionalStuff) { // ... if (optionalStuff) { // do some optional, but important stuff... System.out.println("I'm important sometimes!"); } // ... } 38 But we do write stuff like
  39. 39. JSR-292 java.lang.invoke API A “better reflection” invokedynamic bytecode Allows us to dispatch to linkage logic defined by invoke API 39
  40. 40. invokedynamic We call it “indy” No clear way to express in Java language Important milestone for JVM First new instruction in decades First new JVM feature to only (mainly) target non-java languages 40
  41. 41. java.lang.invoke API MethodHandle CallSite Bootstrap Method (BSM) 41
  42. 42. MethodHandle 42 int foo()Method Handle
  43. 43. MethodHandle Points to a method Is a “function pointer” (am I allowed to say this?) Polymorphic signature 43
  44. 44. MethodHandle Performance 44
  45. 45. MethodHandle Performance Early performance was not ideal 45
  46. 46. MethodHandle Performance Early performance was not ideal Performance improved tremendously with lambda forms 46
  47. 47. MethodHandle Performance Early performance was not ideal Performance improved tremendously with lambda forms Is now often significantly faster than reflection 47
  48. 48. MethodHandle Performance Early performance was not ideal Performance improved tremendously with lambda forms Is now often significantly faster than reflection Can be used independently of invokedynamic 48
  49. 49. CallSite 49 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return CS Method Handle int foo()
  50. 50. CallSite 50 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return CS int bar() int foo()
  51. 51. CallSite Reifies Indy invocation side Has a MethodHandle 51
  52. 52. Bootstrapping Step 1 52 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return
  53. 53. Bootstrapping Step 2 53 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return BootStrap Method
  54. 54. Bootstrapping Step 3 54 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return BootStrap Method int foo()
  55. 55. Bootstrapping Step 4 55 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return BootStrap Method int foo() CS
  56. 56. Bootstrapping Step 5 56 private void doStuff(); descriptor: ()V flags: ACC_PRIVATE Code: stack=2, locals=2, args_size=1 0: new #7 3: dup 4: invokespecial #8 7: astore_1 8: aload_1 9: aload_0 10: invokedynamic #9, 0 15: invokevirtual #10 18: return int foo() CS
  57. 57. Bootstrap Method Only called on the first invocation of each indy bytecode Returns a CallSite 57 "Dr Martens, black, old" by Tarquin is licensed under CC BY-SA 3.0
  58. 58. Indy lifecycle Initial Invocation 1. A specific indy invocation is executed for the first time 2. Bootstrap method is called and if finds (generates?!) a method to run 3. Bootstrap method returns a permanent CallSite object for this indy invocation 4. We jump to the method pointed to by the CallSite 58
  59. 59. Indy Lifecycle All subsequent calls We jump to the method pointed to by the CallSite 59 Picture from National Archives and Records Administration
  60. 60. This performance tragedy becomes 60 Caller Reflection Magic! Callee
  61. 61. 61 Caller Callee MethodHandle
  62. 62. Linkage != Invocation 62
  63. 63. Linkage != Invocation Linkage (i.e. bootstrap) Usually only needs to be done once Is expensive 63
  64. 64. Linkage != Invocation Linkage (i.e. bootstrap) Usually only needs to be done once Is expensive Invocation Done a lot Only needs a jmp/call (and possibly a guard) 64
  65. 65. Linkage != Invocation Avoid the cost of linkage on almost every call 65
  66. 66. • Mismatch between language and bytecode • JDK <= 8 javac uses StringBuilder.append() • StringBuilder has performance issues • JDK >= 9 uses invoke dynamic Copyright © 2019 Oracle and/or its affiliates. String Concatenation
  67. 67. Takeaways 67
  68. 68. Takeaways Invokedynamic lets us programmatically alter linkage 68
  69. 69. Takeaways Invokedynamic lets us programmatically alter linkage Then it gets out of the way! (linkage != invocation) 69
  70. 70. Takeaways Invokedynamic lets us programmatically alter linkage Then it gets out of the way! (linkage != invocation) The Invoke API can often be used without indy 70
  71. 71. Takeaways Invokedynamic lets us programmatically alter linkage Then it gets out of the way! (linkage != invocation) The Invoke API can often be used without indy JVM is a great platform for just about any language! 71
  72. 72. Resources JVM Language Summit http://openjdk.java.net/projects/mlvm/jvmlangsummit/ Linkers & Loaders book http://linker.iecc.com/ John Rose’s Blog https://blogs.oracle.com/jrose/ 72
  73. 73. Thank You! 73
  74. 74. The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation. Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events. Safe Harbor Copyright © 2019 Oracle and/or its affiliates.

×