Explaining invokedynamic. Final notes. Part IX

alex_ber
4 min readSep 8, 2020

This is eighth part of mini-series of Explaining invokedynamic. This is the full list of all articles:

Introduction. Part I

Toy example. Part II

Bootstrap method . Part III

Number multiplication (almost) complete example. Part IV

Dynamical hashCode implementation. Part V

Java 9 String concatenation. Part VI

Lambda. Part VII

Records. Part VII

Final notes. Part IX

Final notes

There is one detail that I didn’t cover: how bootstrap method is registered? You can write some Java method with correct signature, but how it will be used? The short answer: there is no API for registering bootstrap method.

Let’s go back to Java 7. invokedynamic was designed back than to other (dynamic) language that runs on JVM. It wasn’t originally designed for Java Language. invokedynamic is part Java Platform, not the Java Language.

Every language has it’s own compiler. So, such bootstrap has to be registered in such compiler. That compiler, than will emit invokedynamic bytecode instruction, as it did with any other instruction. This instruction will link to bootstrap method on bytecode level. You can even write bootstrap method on your own language, as far it compiles to JVM bytecode, it can be used as bootstrap method.

I want to emphasize this point again. On Java 7 there were no language construct that will be implemented using invokedynamic. So, all resources (at least what I’ve see) use one of two approaches:

  • All example was in bytecode.So, you have to read bytecode in order to understand new concept.
  • Java code use some Java library to emit the bytecode first and than looks on bytecode.In such a way you see some high level construct, so this should easier your understanding of bytecode.

Specifically, ASM or Javassist was popular. AFAIK, this is too low level. You can look on such example here http://niklasschlimm.blogspot.com/2012/02/java-7-complete-invokedynamic-example.html

Than, in Java 8 invokedynamic was decided to be used to implement Lambda expressions. So, javac was changed to recognized new syntax. javac was “teached” to use specific method from the JDK as bootstrap method.

In next version of Java, when invokedynamic the same process of “teaching” java compiler for bootstrap method and when it should be used was done. Bootstrap method was made also non-public to avoid dependence on it’s implementation details.

Now, I want to go over entirety post again to reveal it’s internal structure.

  • It starts with invokestatic and invokevirtual bytecode in order to give you some idea what bytecode is and how it is used. This part is high level and should be easy to grasp to anybody who uses Java.
  • Than there is separate section with concrete code examples that show you what is MethodHandle & CallSite & MethodHandles.Lookup. This part focuses on API usage and enriches your vocabulary, you’re learning concepts that are not well-known. It use following weird construct to trigger invokevirtual:

example.createCallSite(“DOG”).dynamicInvoker().invoke(example)

  • Than I’m giving your another concrete and (almost) complete code examples that is fully written in Java and with limitation of absence of code construct in Java that will trigger invokevirtual. It uses following construct:

DYNAMIC1.multiply(bigNum, bigNum)

that is also weired, but resembles pretty close the real usage.

When you read this example, you should fill comfortable with both language that is used and the API that should be at least somewhat familiar for you at this point.

Than the “real” examples are

  • Simplified String concatenation. This is pretty simple and it demonstrates the full power of bootstrap method in practice. I’m deliberately not showing the actual implementation code here.
  • Simplified Lambda

I want just to “make an reduction” to the previous case. I’m mentioning all important parts of Lambda expressions without going to almost any detail. I’m given only simple Lambda expressions example. I’m deliberately not showing the actual implementation code here.

  • Records

This is the shortest example section. I’m given link to my existed article for broader explanation (I will give more broader explanation sometimes). For the implementation details you can read Dynamical hashCode implementation. Part V (you will find their implementation also toString and equals methods).

Let’s look on how invokedynamic works diagram again.

As I’ve described above, the first part of generating invokedynamic is not well supported in Java. In my “toy” examples some weird construct was used to overcome this limitation.

My “toy” example embeds Implementation logic as static Java code.

Lambda metafactory and StringConcatFactory.makeConcatWithConstants​ (and theire variants) uses some JDK internal API that is similar to ASM. I will not provide it here.

In the real world example, this code is actually generated in runtime by bootsrap method itself. For the “real word” example it is better to look on Dynamical hashCode implementation. Part V This chapter provides implementation details for the Records — preview feature of JDK 14.

--

--