JAVA字节码(一)
例1
public class Helloworld {
public static void main(String[] args) {
System.out.println("hello,world");
}
}
字节码:
public class com.xxx.ch1.Helloworld {
//构造函数
public com.xxx.ch1.Helloworld();
Code:
//aload_0 : 告诉虚拟机,将局部变量this放入操作栈里(位置0 总是默认留给this)
0: aload_0
//调用常量池里(constant pool)的方法
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
//将静态字段压入操作栈,#16指向了常量池里的 System.out 对象
0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
//压入#22所代表的字符串的引用入操作栈
3: ldc #22 // String hello,world
//调用方法常用的指令
5: invokevirtual #24 // Method java/io/PrintStream.println;(Ljava/lang/String;)V
8: return
}
-
aload_0
对于每一个方法(构造函数从字节码角度来讲,也是一个方法,并无区别),方法的参数,以及方法中申明的变量都是在编译期间确定好的,按照出现顺序存放在栈帧里(stack frame)的局部变量表里,位置0 总是默认留给this,其后的位置留给方法的申明参数列表,再之后是留给方法内部用到的局部变量
-
invokespecial
指令要求操作栈(Operand Stack)有一个对象引用,也就是 也就是刚通过aload_0压入的this,invokespecial 其后的参数指向常量池的init方法。正如invokespecial 名字所暗示的那样,此指令只用于一些特殊方法调用,如实例的初始化方法,私有方法,父类方法
例2
public int add(int, int);
Code:
0: iload_1
1: iload_2
2: iadd
3: istore_3
4: iload_3
5: ireturn
- iadd 将操作栈俩个变量想加,i表示操作栈俩个变量是int类型
- istore_3 操作栈结构存回到变量表里,位置索引是3,也就是变量c
- iload_3 因为方法要求返回值,return指令 仍然需要调用操作栈,所以又将变量3压入操作栈里
例3
public List cast(Object a){
List list = (List)a;
return list;
}
public java.util.List cast(java.lang.Object);
Code:
0: aload_1
1: checkcast #16 // class java/util/List
4: astore_2
5: aload_2
6: areturn
java虚拟机有3中引用类型,分别是类类型(class Type),接口类型(interface Type),数组类型(arrayType),分别指向了运行时动态创建的类实例,接口实例,以及数组。如指令checkcast,就要求操作栈里存放的是Refernce Type
例4
public static void main(String[] args) {
int a = 1;
a = a++;
int b = a++;
System.out.println("a="+a);
System.out.println("b="+b);
}
// a=2, b=1
字节码
//将int型常量值1推送至栈顶
0 iconst_1
//将栈顶int型数值存入第二个本地变量 a
1 istore_1
//将第二个int型本地变量 a 推送至栈顶
2 iload_1
//将指定int型变量增加指定值(+1), 之后局部变量 a=2,但是并未压入操作数栈
3 iinc 1 by 1
//将栈顶int型数值(1)存入第二个本地变量 a=1
6 istore_1
//将第二个int型本地变量 a=1 推送至栈顶
7 iload_1
//将指定int型变量增加指定值(+1) a=2
8 iinc 1 by 1
//将栈顶int型数值存入第三个本地变量 b=1
11 istore_2
12 return
例5
public static void main(String[] args) {
int a = 1;
a = ++a;
int b = ++a;
// System.out.println("a="+a);
// System.out.println("b="+b);
}
// a=3, b=3
字节码:
0 iconst_1
1 istore_1
2 iinc 1 by 1 // 局部变量 a=2
5 iload_1 // 压入栈顶:2
6 istore_1 // 栈顶(2)保存至第二个本地变量 a
7 iinc 1 by 1 // 本地变量 a + 1, a=3
10 iload_1 // 压入栈顶 a=3
11 istore_2 // 栈顶(3)保存至第三个本地变量 b
12 return
参考
https://blog.csdn.net/xiandafu/article/details/51458791