[深入理解JVM虚拟机]一段程序的解读

来源:互联网 发布:js中的字符串是否相等 编辑:程序博客网 时间:2024/06/05 03:16

该文主要是为了说明final修饰字符串变量在编译期间会得到优化,使用final申明的字符串变量做字符串拼接会等同于直接申明变量。

源程序:

public class AppMain{    public static void main(String[] args){        String a = "hello2";        final String b = "hello";        String c = "hello";        String d = b + 2;        String e = c + 2;        System.out.println(a == d);// true        System.out.println(a == e);// false    }}

1.编译上段小程序:javac AppMain.java
2.反编译class文件:javap -c AppMain
下面的图片中是该程序反编译后的字节码指令,为了易读所以图片中的字节码指令是省去System.out.println(a == b)与System.out.println(a == e)的结果:
这里写图片描述

3.解读该程序需要了解的字节码指令

  • ldc 将int、float或者String型常量值常量池中推送至栈顶(方法栈中的操作数栈中)
  • astore_1、astore_2、astore_3:将栈顶引用类型的数值存入局部变量表中第二、三、四索引序号的Slot中
  • astore index:将栈顶引用类型的数值存入局部变量表中第index索引序号的Slot中
  • aload_1、aload_2、aload_3:取局部变量表中第index索引项压入栈顶
  • new 创建一个对象,并将其引用压入栈顶
  • dup 复制栈顶数值并将复制值压入栈顶
  • invokespecial:调用构造方法,实例初始化方法,私有方法
  • invokevirtual:调用实例方法

4.运行退main方法,在方法栈弹出前,main方法栈与堆内存中对象说明
这里写图片描述

图例说明:程序运行结果 变量b、c引用的是常量池中hello这项实例,变量a、d应用常量池中hello2这项实例,而变量e指向的是内存中StringBuilder创建的String对象。

0 0