近期学习到字节码操控框架ASM,其中对方法的定义需要设置最大操作数栈和局部变量表。
于是,自己又复习了一遍java栈帧的概念。
如果对栈帧概念还不了解的读者推荐看下此文章:详细解析Java虚拟机的栈帧结构
本文将会通过诸多字节码的例子,来具体分析在不同情况下的方法的操作数栈和局部变量表。
本文的分析主要基于javac和javap的使用:
- 首先用javac生成java文件编译后的class文件
- 再使用"javap -v xxx.class"来输出该class文件的信息
首先要强调个概念:“操作数栈可以复用”。如下两个例子中test方法的操作数栈都会是2。
public class Test {
public int test(int a, int b) {
int c = a + b;
return c;
}
}
public class Test {
public int test(int a, int b) {
int c = a + b;
c = a + b;
c = a + b;
c = a + b;
return c;
}
}
public class Test {
public int test(int a, int b) {
return a + b;
}
}
public int test(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
LineNumberTable:
line 10: 0
public class Test {
private int a = 0;
public int test(int b) {
return a + b;
}
}
public int test(int);
descriptor: (I)I
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: getfield #2 // Field a:I
4: iload_1
5: iadd
6: ireturn
LineNumberTable:
line 11: 0
public class Test {
public int test(int a, int b) {
int c = a + b;
return a + b;
}
}
public int test(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=3
0: iload_1
1: iload_2
2: iadd
3: istore_3
4: iload_1
5: iload_2
6: iadd
7: ireturn
LineNumberTable:
line 10: 0
line 11: 4
public class Test {
public static int test(int a, int b) {
return a + b;
}
}
public static int test(int, int);
descriptor: (II)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=2
0: iload_0
1: iload_1
2: iadd
3: ireturn
LineNumberTable:
line 10: 0
public class Test {
public static int test() {
add("123");
return 0;
}
public static int add(String s) {
}
}
public static int test();
descriptor: ()I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: ldc #2 // String 123
2: invokestatic #3 // Method add:(Ljava/lang/String;)V
5: iconst_0
6: ireturn
LineNumberTable:
line 10: 0
line 11: 5
public class Test {
public static int test() {
new Test().add("123");
return 0;
}
public void add(String s) {
}
}
public static int test();
descriptor: ()I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
0: new #2 // class Test
3: dup
4: invokespecial #3 // Method "":()V
7: ldc #4 // String 123
9: invokevirtual #5 // Method add:(Ljava/lang/String;)V
12: iconst_0
13: ireturn
LineNumberTable:
line 10: 0
line 11: 12