java JVM字节码表示法,注释语法。调用动力学
问题:第14行是什么意思
使用javap-v-c反汇编以下代码:
public class test {
static int i = 2;
public static void main(String[] args) {
test x = new test();
System.out.println("text + String: " + i);
}
}
在主函数中,我们得到以下内容:
14: invokedynamic #20, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
19: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
...
BootstrapMethods:
0: #38 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:
#44 text + String: \u0001
例如,第19行表示从运行时常量池中的#24项调用虚拟函数。调用的方法是来自类java/io/PrintStream
的println()
,其输入来自类Ljava/lang/String
,其返回值为Void
对于第14行,#0保存对BootstrapMethod的引用,并返回一个类为CallSite
的对象,对吗?
然后:
- 20指的是什么李>
- 注释
#0:makeConcatWithConstants:(I)Ljava/lang/String;
是什么意思李>
另外,我在哪里可以找到更多关于Javap反汇编代码语法的信息?或者什么是正确的关键字?甲骨文关于the JVM instruction set
的文档似乎没有明确描述该评论的含义
# 1 楼答案
请参阅the JVM specification:
方便的是,
javap
已经在查找常量池并解码信息;结果是在行中的指令后面打印了一条注释数字},所以这个特定的调用使用一个
#0
是您已经发布的BootstrapMethods
属性的索引。方法名称的含义取决于该引导方法。此外还有type descriptor{int
并产生一个String
运行时将发生什么取决于引用的引导方法。这个调用引用了} ,其中一部分是用Java9编译字符串连接
static
方法^{documentation of that method告诉我们
invokedynamic
指令中使用的方法名是不相关的,BootstrapMethod
属性的静态参数,即text + String: \u0001
确定字符串格式。\u0001
是“普通参数”的占位符,即int
参数# 2 楼答案
简短版本:Java使用invokedynamic连接自Java9以来的字符串
让我们把它分解一下:
InvokedDynamic有两个步骤:
{a2}只是该{a1}的持有者。根据所使用的
CallSite
子类,站点可能会在以后重新链接如果我们看一下说明书,最后会看到以下内容:
第一部分(
#0
)的意思是:Bootstrap方法#0第二部分是名称,它被传递给引导方法,在那里可以使用,也可以不使用
第三部分是结果目标的方法类型。在我们的例子中:一个方法,它接受一个
int
并返回一个java.lang.String
如果我们现在看一下bootstrap方法#0,我们会看到一个方法引用,这里指向StringConcatFactory.makeConcatWithConstants(...)。 我们还看到另外一个参数:字符串
"text + String: \u0001"
引导方法的任务现在是返回一个MethodHandle(在调用站点内部),在本例中,它执行字符串连接。但是它是如何进行字符串连接的(StringBuilder、string.format、字节码旋转、链接方法句柄…)对于实际的类来说并不重要。它只希望串接字符串
让我们试着用手模仿这种行为。毕竟,bootstrap方法是一种普通的Java方法:
(VM会做更多的事情,比如它会记住结果,不会再次调用bootstrap方法,但对于我们的小示例来说,这已经足够好了)
在这一点上,我们可以深入了解引导方法是如何工作的
事实证明:您可以将VM配置为使用不同的策略
它使用它在
java.base
内的特权位置访问java的包私有构造函数。不复制数组的lang.String-如果之后不修改内容,这是安全的默认策略是MethodHandle链接
好消息是:如果有人在某个时候写了一个更好的策略,您的程序将从中受益,而无需重新编译