简单了解Java字节码

java的“一处编译、多处执行”,得益于它的字节码和JVM。字节码就是java编译后的能被JVM读懂的类汇编语言。

1.举个例子:

package jvm;

public class A {
}

上面是一个最简单的类,编译该类:

javac A.java

生成对应的A.class文件,反编译该class:

javap A.class
Compiled from "A.java"
public class jvm.A {
  public jvm.A();
}

反编译后,可以看到默认的构造函数jvm.A()。
如果要看到字节码,可以使用如下的命令:

javap -c A.class 
Compiled from "A.java"
public class jvm.A {
  public jvm.A();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
}

简单解释一下:
aload_0 表示将第一个变量(引用类型)压入堆栈,对于非静态方法,第一个引用变量是this,即将this指针压栈。aload_0的16进制代码为0x2a
invokespecial 表示调用超类构造方法,其十六进制码为0xb7
return 表示当前方法返回void,其十六进制码为0xb1

2.更复杂些的例子

package jvm;

public class A {
	public int add(int a, int b) {
        return a + b;
    }
}

更复杂些的类A,编译再反编译后,可以看到如下的字节码:

javap -c A.class 
Compiled from "A.java"
public class jvm.A {
  public jvm.A();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public int add(int, int);
    Code:
       0: iload_1
       1: iload_2
       2: iadd
       3: ireturn
}

默认的构造函数之外,增加了新的方法int add(int, int),它的字节码解释如下:
iload_1 将第二个变量(int类型)压栈
iload_2 将第三个变量(int类型)压栈
iadd 将栈顶两int型数值相加并将结果压入栈顶
ireturn 返回int类型
注意,之所以是iload_1而不是iload_0是因为目前是非静态方法,第一个变量默认为this。如果上述add方法换为静态方法,则反编译后,字节码如下:

javap -c A.class 
Compiled from "A.java"
public class jvm.A {
  public jvm.A();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static int add(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: iadd
       3: ireturn
}

后续文章还会接着本文的例子聊下.class文件的结构。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值