【发布时间】:2021-06-15 15:39:32
【问题描述】:
我正在研究类文件的 StackMapTable 属性,我有一些问题,堆栈映射框架是如何计算的?
这里有两个例子:
例子1
public class Foo {
public void foo() {
int i = 0;
int j = 0;
if (i > 0) {
int k = 0;
}
int l = 0;
}
}
//byte code:
public void foo();
Code:
Stack=1, Locals=4, Args_size=1
0: iconst_0
1: istore_1
2: iconst_0
3: istore_2
4: iload_1
5: ifle 10
8: iconst_0
9: istore_3
10: iconst_0
11: istore_3
12: return
LocalVariableTable:
Start Length Slot Name Signature
10 0 3 k I
0 13 0 this LFoo;
2 11 1 i I
4 9 2 j I
12 1 3 l I
StackMapTable: number_of_entries = 1
frame_type = 253 /* append */
offset_delta = 10
locals = [ int, int ]
示例 2
public static void chop() {
int i = 0;
int j = 0;
if (i > 0) {
long k = 0;
if (j == 0) {
k++;
int s=1111;
}
int t = 0;
}
}
//bytecode
public static void chop();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=5, args_size=0
0: iconst_0
1: istore_0
2: iconst_0
3: istore_1
4: iload_0
5: ifle 26
8: lconst_0
9: lstore_2
10: iload_1
11: ifne 23
14: lload_2
15: lconst_1
16: ladd
17: lstore_2
18: sipush 1111
21: istore 4
23: iconst_0
24: istore 4
26: return
LineNumberTable:
line 34: 0
line 35: 2
line 36: 4
line 37: 8
line 38: 10
line 39: 14
line 40: 18
line 42: 23
line 44: 26
StackMapTable: number_of_entries = 2
frame_type = 254 /* append */
offset_delta = 23
locals = [ int, int, long ]
frame_type = 250 /* chop */
offset_delta = 2
谁能根据这两个例子介绍如何计算堆栈图框架?
这个问题困扰了我很久,任何帮助将不胜感激!谢谢!
【问题讨论】:
-
“计算”是什么意思?这是什么意思?
-
栈映射表你了解多少?你不明白的实际点是什么?
-
也许你应该先阅读What is a stack map frame。然后,您应该了解条目的数量。正如链接的答案所说,“它们通常表示为与前一帧的差异以减少数据大小”,因此当您了解其结构时,您应该了解附加或切分类型的含义。您可以从字节码计算堆栈帧,这是旧验证器所做的,也是 ASM 库支持的,但正如 this answer 中所述,它有局限性。
-
分支目标、异常处理程序的开始以及无法访问的指令序列的开始都需要堆栈映射表中的条目。如果这些点让你感觉更好,你可以把这些点称为一个基本块的开始,但这并没有什么区别。是的,对于您的第二种方法,这些是字节码位置 23 和 26。
-
您是指
LocalVariableTable吗?这是一个调试功能。它提供有关变量的信息,因为它们出现在源代码中。StackMapTable是验证者的一个属性,它与字节码中使用的变量有关。例如,前者是可选的并且包含名称,后者是强制性的并且不关心名称。
标签: java class bytecode java-bytecode-asm