使用"invokedynamic" - 引擎盖下发生了什么?



背景

我目前正在用C#编写JVM,纯粹是为了学术目的(将来可能还会构建一个.NET和Java/Scala混合的应用程序(。

上下文

我编写了简单的JAVA类:

public class test
{
public static String hello_world(int i)
{
return "Hello " + i + " World!";
}
}

并将其编译为CCD_ 1。当我用我的反编译器(我已经将其作为JVM的一部分编写(对其进行反编译时,我看到了该方法的以下说明:

iload_0
invokedynamic 2
areturn

当在常量池中查找索引2处的常量时,我看到一个InvokeDynamic constant条目,其中包含以下数据:

makeConcatWithConstants : (I)Ljava/lang/String;

我想这是有道理的(我更像是一个.NET用户,而不是JAVA用户(。

当使用参数1执行我的方法hello_world时,在执行invokedynamic 2之前,我有以下堆栈:

----TOP---
0x00000001
--BOTTOM--

问题

我的问题是:如何使用invokedynamic
我无法解析方法makeConcatWithConstants,因为InvokeDynamic常量不会给我任何makeConcatWithConstants可能所在的提示(请参阅文档(。
堆栈也不包含对堆的引用,指示方法makeConcatWithConstants可以与哪个实例类型关联。

我通读了test.class0文档,但我不理解它(也许我被.NET框架"损坏"了很多(

有人能给我举个例子,说明在执行这三条指令时JVM的引擎盖下发生了什么吗?(invokedynamic的被叫方期望什么等等(?

我已经在JVM中实现了invokestatic。。。但我目前无法理解CCD_ 13。

invokedynamic的思想是;当第一次遇到这个字节码时,调用一个引导方法,该方法创建一个Callsite对象,该对象链接到需要调用的实际方法。

在实践中,这通常意味着您动态地创建调用的实现。

如果你用javap -v test查看你的程序,你会在底部看到一个BootstrapMethods属性:

BootstrapMethods:
0: #15 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
Method arguments:
#16 Hello u0001 World!

您可以看到这个特定调用站点的引导方法位于StringConcatFactory

Method arguments是一组常量参数。

LookupStringMethodType的前导自变量分别为;具有与调用站点相同的权限、某些名称和调用站点类型的查找对象。第一个需要由VM在运行时提供,后两个由invokedynamic常量池条目以名称和类型的形式提供:

#2 = InvokeDynamic      #0:#17         // #0:makeConcatWithConstants:(I)Ljava/lang/String;

因此,要实现这个字节码,必须有一些机制来创建查找对象,然后才能调用引导方法。之后,您可以在返回的Callsite对象上调用dynamicInvoker(),这会给您一个MethodHandle,然后您应该为这个特定的调用站点缓存它,然后(最后(调用它。

如果你想看看这是如何在OpenJDK中实现的,你可以在这里找到实现:http://hg.openjdk.java.net/jdk/jdk/file/tip/src/hotspot/share/interpreter/bytecodeInterpreter.cpp#l2446

我猜在项目的早期阶段,这可能太棘手了,所以现在用-XDstringConcat=inline编译程序可能更容易,因为它使用了传统的StringBuilder级联,实现起来应该更简单。

相关内容

  • 没有找到相关文章

最新更新