背景
我目前正在C#中编写一个JVM,纯粹是为了学术目的(也许将来还会构建一个混合的.NET和Java/Scala应用程序)。
上下文
我编写了简单的类:
public class test
{
public static String hello_world(int i)
{
return "Hello " + i + " World!";
}
}并将其编译成test.class。当我用我的反编译器(我作为JVM的一部分编写)反编译它时,我看到了关于这个方法的以下说明:
iload_0
invokedynamic 2
areturn当在常量池中查看索引2上的常量时,我看到一个InvokeDynamic常量条目,其中包含以下数据:
makeConcatWithConstants : (I)Ljava/lang/String;这是有意义的,我想(我更多的是一个.NET用户而不是一个JAVA用户)。
当使用参数hello_world执行我的方法1时,在执行invokedynamic 2之前有以下堆栈
----TOP---
0x00000001
--BOTTOM--问题
我的问题是:如何使用invokedynamic**?** ?
我无法解析方法makeConcatWithConstants,因为InvokeDynamic常量没有给我任何提示,makeConcatWithConstants可能位于哪里(见文件)。
堆栈也不包含对堆的引用,指示可以与makeConcatWithConstants关联的方法的实例类型。
我读过文档,但我不明白(也许我被.NET-Framework“损坏”了)。
有人能给我举个例子,说明在执行这三个指令时JVM的引擎盖下发生了什么吗?( invokedynamic的要求是什么?)
我已经在我的invokestatic中实现了.但我目前无法理解invokedynamic。
发布于 2018-11-04 11:08:01
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是一组常量参数。
Lookup、String和MethodType的前导参数分别是:具有与回调站点相同的优先级的查找对象、名称和回调站点的类型。其中的第一个需要在运行时由VM提供,而后面的2个则由以名称和类型的形式提供:
#2 = InvokeDynamic #0:#17 // #0:makeConcatWithConstants:(I)Ljava/lang/String;因此,要实现这个字节码,就必须有一些机制来创建查找对象,然后才能调用引导方法。之后,您可以对返回的dynamicInvoker()对象调用Callsite,这为您提供了一个MethodHandle,然后您应该缓存这个特定的调用站点,然后(最后)调用。
如果您想看看这是如何在OpenJDK中实现的,您可以在这里找到实现:http://hg.openjdk.java.net/jdk/jdk/file/tip/src/hotspot/share/interpreter/bytecodeInterpreter.cpp#l2446
我猜在这个项目的早期阶段,这可能太棘手了,所以现在用-XDstringConcat=inline编译您的程序可能会更容易,因为它使用了遗留的StringBuilder连接,这应该更容易实现。
https://stackoverflow.com/questions/53139737
复制相似问题