我正在研究类文件的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
有人能介绍一下如何在这两个例子的基础上计算堆栈映射帧吗
这个问题困扰我很长时间了,如果有任何帮助,我们将不胜感激!谢谢
示例1:
public class Foo {
public void foo() {
int i = 0;
int j = 0;
if (i > 0) {
int k = 0;
}
int l = 0;
}
}
foo
方法的操作码和帧:
foo:()V
// {this} | {} <--- initial frame
0000: iconst_0 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_0 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: ifle 5 // {this, int, int} | {}
0008: iconst_0 // {this, int, int} | {int}
0009: istore_3 // {this, int, int, int} | {}
// {this, int, int} | {} <--- second frame
0010: iconst_0 // {this, int, int} | {int}
0011: istore_3 // {this, int, int, int} | {}
0012: return // {} | {}
初始帧由方法访问和方式描述符自动计算:
{this} | {}
第二帧是ifle
操作码(0005
(的跳转目标:
{this, int, int} | {}
将第二帧与 初始帧示例2: 将第二帧与 初始帧将第三帧与的第二帧public class Foo {
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;
}
}
}
chop
方法的操作码和帧:chop:()V
// {} | {} <--- initial frame
0000: iconst_0 // {} | {int}
0001: istore_0 // {int} | {}
0002: iconst_0 // {int} | {int}
0003: istore_1 // {int, int} | {}
0004: iload_0 // {int, int} | {int}
0005: ifle 21 // {int, int} | {}
0008: lconst_0 // {int, int} | {long, top}
0009: lstore_2 // {int, int, long, top} | {}
0010: iload_1 // {int, int, long, top} | {int}
0011: ifne 12 // {int, int, long, top} | {}
0014: lload_2 // {int, int, long, top} | {long, top}
0015: lconst_1 // {int, int, long, top} | {long, top, long, top}
0016: ladd // {int, int, long, top} | {long, top}
0017: lstore_2 // {int, int, long, top} | {}
0018: sipush 1111 // {int, int, long, top} | {int}
0021: istore 4 // {int, int, long, top, int} | {}
// {int, int, long, top} | {} <--- second frame
0023: iconst_0 // {int, int, long, top} | {int}
0024: istore 4 // {int, int, long, top, int} | {}
// {int, int} | {} <--- third frame
0026: return // {} | {}