Java invokedynamic

Invokedynamic is a JVM bytecode instruction for invoking methods, which facilitates runtime type checking. Before invokedynamic was introduced in Java 1.7, we had 4 opcodes for calling methods:

  • invokevirtual – used for public and protected instance methods
  • invokestatic – used for static methods
  • invokeinterface – used for methods call through an interface
  • invokespecial – used for calling exact methods, like constructors and private methods
private void initGreetingArrays() {
	List list = new ArrayList<>(); //invokespecial
	list.add("Hello"); //invokeinterface

	ArrayList anotherList = new ArrayList<>(); //invokespecial
	anotherList.add("Hi"); //invokevirtual
}

Java is by default a statically-typed language. It performs type checking during compilation. Invokedynamic allows application-level code to determine which method a call will execute, and to do so only when the call is about to execute. This allows language and framework writers to support much more dynamic programming styles than the Java platform previously provided.

When Java 7 arrived, the JVM had support for executing the new bytecode, but regardless of the Java code submitted, javac would never produce bytecode that included invokedynamic. Instead, the feature was used to support JRuby and other dynamic languages running on the JVM.

For invokedynamic to work correctly, a key concept is the method handle. This is a way to represent the method that should be called from the invokedynamic call site. The general idea is that each invokedynamic instruction is associated with a special method (known as a bootstrap method or BSM). When the invokedynamic instruction is reached by the interpreter, the BSM is called. It returns an object (containing a method handle) that indicates which method the call site should actually execute.

This is somewhat similar to reflection, but reflection has limitations that made it unsuitable for use with invokedynamic. Instead, the java.lang.invoke.MethodHandle (and subclasses) were added to the Java 7 API, to represent methods that invokedynamic can target. The class MethodHandle receives some special treatment from the JVM, in order to operate correctly.

Java 8 compiler uses invokedynamic for lambda expressions.

Invokedynamic resources I used to compile this summary: