从常量池 Java 字节码访问值
Accessing values from Constant Pool Java Bytecode
我有以下代码:
public static void f(){
double i = 0.0;
for(i = 0.0; i<100.0; i++){}
}
转换为以下字节码:
public static void f();
Code:
0: dconst_0
1: dstore_0
2: dconst_0
3: dstore_0
4: dload_0
5: ldc2_w #2 // double 100.0d
8: dcmpg
9: ifge 19
12: dload_0
13: dconst_1
14: dadd
15: dstore_0
16: goto 4
19: return
我对包含评论 //double 100.0d
的行感到困惑
我有点理解 ldc2_w
的作用。它从常量池中获取适当的常量。并且常量池在解析 Java 代码后包含一个定义的常量列表,对吗?
但是#2
的目的是什么?怎么知道这里应该放几号呢?在在线教程中,我看到有人改用 #4
?
这个操作数是什么意思?
#2
是该常量在常量池中的索引,即常量池中的第 2 个条目。注意常量池还有其他的入口,包括方法名、字符串等。
通常编译器将java代码翻译成字节码指令并同时添加任何需要的常量池条目。请参阅 JVM Specification. There are also bytecode manipulation frameworks like ASM and bytecode assemblers like Jasmin 中的常量池数据结构的详细信息,它完全从开发人员那里抽象出常量池填充。
But what is the purpose of #2? How would one know what number should
go here? On an online tutorial I saw someone use #4 instead?
通常你不会。如果您正在编写字节码汇编,您通常依赖汇编程序为您填充常量池。
例如,如果你写
ldc2_w 100.0
在Jasmin或者Krakatau中,汇编器会自动为100.0建立一个常量池入口,然后填入合适的索引。可能是2,可能是4,可能是50000。这取决于常量池中还有什么,但你通常不关心那个。
Krakatau 汇编器还允许您手动指定常量池条目。所以如果你想确保你的替身在位置 2,你可以做
.const [2] = Double 100.0
ldc2_w [2]
然而,几乎没有任何理由这样做。这仅在您关心类文件的确切二进制布局时才有用。
至于为什么您会看到第 2 个,那是因为 Javap 就是这样。它用于快速检查字节码。如果你使用不同的工具,你会得到不同的结果。例如,除非您指定往返模式,否则 Krakatau 反汇编器只会打印出 ldc2_w 100.0
。
我有以下代码:
public static void f(){
double i = 0.0;
for(i = 0.0; i<100.0; i++){}
}
转换为以下字节码:
public static void f();
Code:
0: dconst_0
1: dstore_0
2: dconst_0
3: dstore_0
4: dload_0
5: ldc2_w #2 // double 100.0d
8: dcmpg
9: ifge 19
12: dload_0
13: dconst_1
14: dadd
15: dstore_0
16: goto 4
19: return
我对包含评论 //double 100.0d
我有点理解 ldc2_w
的作用。它从常量池中获取适当的常量。并且常量池在解析 Java 代码后包含一个定义的常量列表,对吗?
但是#2
的目的是什么?怎么知道这里应该放几号呢?在在线教程中,我看到有人改用 #4
?
这个操作数是什么意思?
#2
是该常量在常量池中的索引,即常量池中的第 2 个条目。注意常量池还有其他的入口,包括方法名、字符串等。
通常编译器将java代码翻译成字节码指令并同时添加任何需要的常量池条目。请参阅 JVM Specification. There are also bytecode manipulation frameworks like ASM and bytecode assemblers like Jasmin 中的常量池数据结构的详细信息,它完全从开发人员那里抽象出常量池填充。
But what is the purpose of #2? How would one know what number should go here? On an online tutorial I saw someone use #4 instead?
通常你不会。如果您正在编写字节码汇编,您通常依赖汇编程序为您填充常量池。
例如,如果你写
ldc2_w 100.0
在Jasmin或者Krakatau中,汇编器会自动为100.0建立一个常量池入口,然后填入合适的索引。可能是2,可能是4,可能是50000。这取决于常量池中还有什么,但你通常不关心那个。
Krakatau 汇编器还允许您手动指定常量池条目。所以如果你想确保你的替身在位置 2,你可以做
.const [2] = Double 100.0
ldc2_w [2]
然而,几乎没有任何理由这样做。这仅在您关心类文件的确切二进制布局时才有用。
至于为什么您会看到第 2 个,那是因为 Javap 就是这样。它用于快速检查字节码。如果你使用不同的工具,你会得到不同的结果。例如,除非您指定往返模式,否则 Krakatau 反汇编器只会打印出 ldc2_w 100.0
。