Invoke Dynamic

Table of Contents

1. Invoke Dynamic

1.1. Overview

invokedynamic 是 java 1.7 添加一个新的 JVM OPCODE, 主要用来支持动态类型语言. 在 java 1.8 中, OpenJDK 使用 invokedynamic 来实现 lambda.

invokedynamic 要解决的主要问题是:

function (x) {
    x.foo();
}

应该编译为什么样的 bytecode? x 的类型是未知的, 那么 `x.foo()` 应该编译成 invoke-?

invokedynamic 的思想是:

由于 x 的类型只有在运行时才能知道, 当需要确定 `x.foo` 如何 dispatch 时,把调用时相关的信息 (例如 x 对象, 字符串 "foo", foo 的 method type 或 signature) 作为参数传递给一个用户提供的 bootstrap 函数, 后者会返回一个 CallSite 对象, 包含了具体的对应于当前 callsite 的 target function (MethodHandle), 即由用户去实现具体的 dispatch.

  1. invokedynamic 调用时是由 bootstrap 函数决定具体的 dispatch
  2. bootstrap 函数是用户可以提供的, 给各种动态语言基于 JVM 的实现提供了灵活性, 它相当于 linker 中的 dl_resolve 函数
  3. invokedynamic 相当于 `userspace` 的 dispatch

1.2. invokedynamic 与 lambda

OpenJDK 中 lambda 的实现:

import java.util.function.Consumer;
import java.util.ArrayList;

public class playground {
    static void foo(Consumer<String> c) {
        c.accept("hello");
    }

    public static void main(String[] args) {
        foo(v -> {int x = v.length();});
    }
}

对应的 bytecode 为:

public static void main(java.lang.String[]);
  0: invokedynamic #4,  0              // InvokeDynamic #0:accept:()Ljava/util/function/Consumer;
  5: invokestatic  #5                  // Method foo:(Ljava/util/function/Consumer;)V
  8: return

private static void lambda$main$0(java.lang.String);
  0: aload_0
  1: invokevirtual #6                  // Method java/lang/String.length:()I
  4: istore_1
  5: return

bootstrap method:
0: #28 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #29 (Ljava/lang/Object;)V
      #30 invokestatic playground.lambda$main$0:(Ljava/lang/String;)V
      #31 (Ljava/lang/String;)V

与 类似, 首先 lambda 被编译为一个 static 函数, 然后由 invokedynamic 在运行时通过 metafactory 这个 bootstrap 函数提供了一个与 LambdaConsumer 类似的 functional interface 的实例 ((通过 ASM 框架)

Author: [email protected]
Date: 2019-08-20 Tue 00:00
Last updated: 2022-02-26 Sat 00:02

知识共享许可协议