Java—Jvm字节码实例解析

本文不对字节码中的每一个指令进行解析,只对几个实例进行解析,以此来了解java文件编译后生产的class字节码。实例中所有所有代码均可直接使用,建议自己重新实验一下。JVM字节码在通常开发情况下没有用处,但是是一种无侵入监控方法(动态字节码技术)、匪夷所思的BUG调试的重要技术手段。

一、环境

(1)JDK1.7

(2)javac Test.java 生产Test.class

(3)javap -c Test.class > test.txt 输出JVM字节码


二、字节码实例

字符串

StringAppend类为例

源码如下:

package com.owl.zookeeper.string;
public class StringAppend {
    public static void main(String[] args) {
        String a = "1";
        String b = "2" + a + "3";
        System.out.println(b);
    }
}
字节码如下:
 Compiled from "StringAppend.java"
 public class com.owl.zookeeper.string.StringAppend {
 public com.owl.zookeeper.string.StringAppend();
 Code:
 0: aload_0  //将this入栈
 1: invokespecial #1                  // Method java/lang/Object."<init>":()V //调用Object的构造方法
 4: return                            //返回void

 public static void main(java.lang.String[]);
 Code:
 0: ldc           #2                  // String 1  解释:LDC cst:将常量池偏移量为cst的值入栈,譬如LDC #12,在操作栈中会占用1个字长
 2: astore_1                          解释:将栈顶的String 1赋值给第一个变量a
 3: new           #3                  // class java/lang/StringBuilder 解释:创建对象,并将该对象入栈顶
 6: dup                               解释:复制栈顶数据StringBuilder。因为方法调用会弹出参数(这里是Object对象),因此需要上面的dup指令,保证在调用构造函数之后栈顶上还是 Object对象的引用,很多种情况下dup指令都是为这个目的而存在的。
 7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V 解释:调用StringBuilder构造方法
 10: ldc           #5                  // String 2 解释:将String 2压入栈顶
 12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 解释:栈顶2出栈,作为方法入参,调用java/lang/StringBuilder.append()方法
 15: aload_1                           解释:将变量a的1入栈
 16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 解释:将变量a的1出栈,作为方法入参,调用java/lang/StringBuilder.append()方法
 19: ldc           #7                  // String 3 解释:将常量池中的字符串3入栈
 21: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 解释:将字符串3出栈,作为方法入参,调用java/lang/StringBuilder.append()方法
 24: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 解释:调用StringBuilder.toString
 27: astore_2                          解释:将返回值保存在变量b
 28: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream; 解释:获得静态变量,System.out
 31: aload_2                           解释:变量2入栈
 32: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 解释:变量2出栈,作为println的方法
 35: return                            解释:返回


循环

StringForAppend类为例

源码如下:

public class StringForAppend {
    public static void main(String[] args) {
        String a = "";
        for(int i = 0; i < 3; i ++) {
            a += "1";
        }
        System.out.println(a);
    }
}

字节码如下:

 Compiled from "StringForAppend.java"
 public class com.owl.zookeeper.string.StringForAppend {
 public com.owl.zookeeper.string.StringForAppend();
 Code:
 0: aload_0
 1: invokespecial #1                  // Method java/lang/Object."<init>":()V
 4: return

 public static void main(java.lang.String[]);
 Code:
 0: ldc           #2                  // String 解释:将常量空字符串入栈
 2: astore_1                          解释:将空字符串赋值给a
 3: iconst_0                          解释:将常量integer 0入栈
 4: istore_2                          解释:出栈0,赋值给变量0
 5: iload_2                           解释:将变量i=0,入栈
 6: iconst_3                          解释:将integer 3入栈
 7: if_icmpge     36                  解释:比较栈顶两个元素,如果相等则跳转到36
 10: new           #3                  // class java/lang/StringBuilder 创建StringBuilder,并入栈
 13: dup                               解释:复制栈顶
 14: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V 解释:出栈调用StringBuilder的构造方法
 17: aload_1                           解释:入栈空字符串
 18: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 出栈空字符串,出栈StringBuilder,执行append方法
 21: ldc           #6                  // String 1 解释:常量1入栈
 23: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 出栈字符串1,调用append方法
 26: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 出栈StringBuilder,调用append方法,将结果入栈
 29: astore_1                          解释:出栈""+1,保存到变量a
 30: iinc          2, 1                解释:将变量i,递增1
 33: goto          5                   解释:跳转到步骤5
 36: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;解释:获得对象PrintStream,入栈
 39: aload_1                           解释:入栈变量a
 40: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V 出栈变量a,出栈PrintStream,调用println方法
 43: return                            解释:返回


判断

StringIf类为例

源码如下:

public class StringIf {
    public static void main(String[] args) {
        String a = "123";
        if("123" == (a)) {
            System.out.println(a);
        }else {
            String b = a + "!";
            System.out.println(b);
        }
    }
}

字节码如下:

 Compiled from "StringIf.java"
 public class com.owl.zookeeper.string.StringIf {
 public com.owl.zookeeper.string.StringIf();
 Code:
 0: aload_0
 1: invokespecial #1                  // Method java/lang/Object."<init>":()V
 4: return

 public static void main(java.lang.String[]);
 Code:
 0: ldc           #2                  // String 123 解释:将常量123入栈
 2: astore_1                          解释:出栈123,赋值给变量a
 3: ldc           #2                  // String 123  解释:将常量123入栈
 5: aload_1                           解释:入栈123
 6: if_acmpne     19                  解释:比较栈顶两个元素,如果符合跳转到指定位置
 9: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;解释:获得System.out对象,入栈
 12: aload_1                          解释:入栈123
 13: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V 解释:出栈参数,出栈调用方法对象
 16: goto          46                  解释:跳转到结束
 19: new           #5                  // class java/lang/StringBuilder 创建一个 解释:创建一个StringBuilder对象,并入栈
 22: dup                               解释:复制栈顶数据,并入栈
 23: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V 解释:出栈并调用构造方法
 26: aload_1                           解释:入栈123
 27: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;解释:出栈123,出栈StringBUilder,调用方法,入栈StirngBuilder
 30: ldc           #8                  // String ! 解释:入栈常量!
 32: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;解释:出栈!,出栈StringBuilder,调用append(!),入栈StirngBuilder
 35: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 解释:出栈StringBuilder,调用toString()
 38: astore_2                          解释:出栈123!,赋值给变量b
 39: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream; 解释:获得PrintStream,并入栈
 42: aload_2                           解释:入栈123!
 43: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V  出栈2个栈位,调用println
 46: return                            解释:返回


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值