Invokedynamic 工厂将 lambdas 创建为单例?
Invokedynamic factory creates lambdas as a singleton?
例如,我有两个 lambda:
Runnable exec1 = () -> {
System.out.print("Hi from lambda");
};
Runnable exec2 = () -> {
System.out.print("Hi from lambda");
};
Invokedynamic 运算符将使用特殊工厂创建它
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;
但是我在读取字节码时遇到了一些问题。这是否意味着,在这种情况下,该工厂将缓存 lambda 创建(并且 exec2
将重用实例)?
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 6 L0
INVOKEDYNAMIC run()Ljava/lang/Runnable; [
// handle kind 0x6 : 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;
// arguments:
()V,
// handle kind 0x6 : INVOKESTATIC
test/Main.lambda$main[=12=]()V,
()V
]
ASTORE 1
L1
LINENUMBER 10 L1
INVOKEDYNAMIC run()Ljava/lang/Runnable; [
// handle kind 0x6 : 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;
// arguments:
()V,
// handle kind 0x6 : INVOKESTATIC
test/Main.lambda$main()V,
()V
]
ASTORE 2
L2
LINENUMBER 13 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE exec Ljava/lang/Runnable; L1 L3 1
LOCALVARIABLE exec2 Ljava/lang/Runnable; L2 L3 2
MAXSTACK = 1
MAXLOCALS = 3
// access flags 0x100A
private static synthetic lambda$main()V
L0
LINENUMBER 11 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hi from lambda"
INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V
L1
LINENUMBER 12 L1
RETURN
MAXSTACK = 2
MAXLOCALS = 0
// access flags 0x100A
private static synthetic lambda$main[=12=]()V
L0
LINENUMBER 7 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hi from lambda"
INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V
L1
LINENUMBER 8 L1
RETURN
MAXSTACK = 2
MAXLOCALS = 0
}
首先,您需要了解 call-site
是什么;能够理解 缓存 发生的位置。 exec1
和 exec2
都会创建两个单独的 Runnable
接口实例;两者都将缓存在 call-site
上。也许这个小片段会有所帮助:
public static void main(String[] args) {
useStatelessLambda1();
useStatelessLambda1();
useStatelessLambda2();
useStatelessLambda2();
}
static void useStatelessLambda1() {
Runnable exec1 = () -> {
System.out.print("Hi from lambda");
};
System.out.print(exec1.hashCode() + " ");
exec1.run();
System.out.println("\n");
}
static void useStatelessLambda2() {
Runnable exec2 = () -> {
System.out.print("Hi from lambda");
};
System.out.print(exec2.hashCode() + " ");
exec2.run();
System.out.println("\n");
}
运行 这表明:
1878246837 Hi from lambda
1878246837 Hi from lambda
1995265320 Hi from lambda
1995265320 Hi from lambda
单独的 个实例,但都缓存 在调用站点.
不管怎样,查看字节码不会告诉你任何相关信息。您可以查看 invokedynamic
将使用的 bootstrap 方法:LambdaMetafactory::metafactory
并了解它的作用。
例如,我有两个 lambda:
Runnable exec1 = () -> {
System.out.print("Hi from lambda");
};
Runnable exec2 = () -> {
System.out.print("Hi from lambda");
};
Invokedynamic 运算符将使用特殊工厂创建它
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;
但是我在读取字节码时遇到了一些问题。这是否意味着,在这种情况下,该工厂将缓存 lambda 创建(并且 exec2
将重用实例)?
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 6 L0
INVOKEDYNAMIC run()Ljava/lang/Runnable; [
// handle kind 0x6 : 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;
// arguments:
()V,
// handle kind 0x6 : INVOKESTATIC
test/Main.lambda$main[=12=]()V,
()V
]
ASTORE 1
L1
LINENUMBER 10 L1
INVOKEDYNAMIC run()Ljava/lang/Runnable; [
// handle kind 0x6 : 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;
// arguments:
()V,
// handle kind 0x6 : INVOKESTATIC
test/Main.lambda$main()V,
()V
]
ASTORE 2
L2
LINENUMBER 13 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE exec Ljava/lang/Runnable; L1 L3 1
LOCALVARIABLE exec2 Ljava/lang/Runnable; L2 L3 2
MAXSTACK = 1
MAXLOCALS = 3
// access flags 0x100A
private static synthetic lambda$main()V
L0
LINENUMBER 11 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hi from lambda"
INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V
L1
LINENUMBER 12 L1
RETURN
MAXSTACK = 2
MAXLOCALS = 0
// access flags 0x100A
private static synthetic lambda$main[=12=]()V
L0
LINENUMBER 7 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hi from lambda"
INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V
L1
LINENUMBER 8 L1
RETURN
MAXSTACK = 2
MAXLOCALS = 0
}
首先,您需要了解 call-site
是什么;能够理解 缓存 发生的位置。 exec1
和 exec2
都会创建两个单独的 Runnable
接口实例;两者都将缓存在 call-site
上。也许这个小片段会有所帮助:
public static void main(String[] args) {
useStatelessLambda1();
useStatelessLambda1();
useStatelessLambda2();
useStatelessLambda2();
}
static void useStatelessLambda1() {
Runnable exec1 = () -> {
System.out.print("Hi from lambda");
};
System.out.print(exec1.hashCode() + " ");
exec1.run();
System.out.println("\n");
}
static void useStatelessLambda2() {
Runnable exec2 = () -> {
System.out.print("Hi from lambda");
};
System.out.print(exec2.hashCode() + " ");
exec2.run();
System.out.println("\n");
}
运行 这表明:
1878246837 Hi from lambda
1878246837 Hi from lambda
1995265320 Hi from lambda
1995265320 Hi from lambda
单独的 个实例,但都缓存 在调用站点.
不管怎样,查看字节码不会告诉你任何相关信息。您可以查看 invokedynamic
将使用的 bootstrap 方法:LambdaMetafactory::metafactory
并了解它的作用。