常量池和局部变量表(四)

这里都是针对jdk1.8的hotspot虚拟机讲解 

public class Demo1_1{
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
        String s4 = s1+s2;
        String s5 = "a" + "b";
        
    }
}

 

通过在命令窗口反编译class文件得到如下信息: 认识二进制字节码文件内容(三)
 

D:\workspace\day01easyjdbc01\target\classes\com\demo\jvm>javap -v Demo1_1.class
Classfile /D:/workspace/day01easyjdbc01/target/classes/com/demo/jvm/Demo1_1.class
  Last modified 2020-3-29; size 706 bytes
  MD5 checksum 0ba87b6925bb2d842174a3e3f4a1c3df
  Compiled from "Demo1_1.java"
public class com.demo.jvm.Demo1_1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #10.#30        // java/lang/Object."<init>":()V
   #2 = String             #31            // a
   #3 = String             #32            // b
   #4 = String             #33            // ab
   #5 = Class              #34            // java/lang/StringBuilder
   #6 = Methodref          #5.#30         // java/lang/StringBuilder."<init>":()V
   #7 = Methodref          #5.#35         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #8 = Methodref          #5.#36         // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Class              #37            // com/demo/jvm/Demo1_1
  #10 = Class              #38            // java/lang/Object
  #11 = Utf8               <init>
  #12 = Utf8               ()V
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               LocalVariableTable
  #16 = Utf8               this
  #17 = Utf8               Lcom/demo/jvm/Demo1_1;
  #18 = Utf8               main
  #19 = Utf8               ([Ljava/lang/String;)V
  #20 = Utf8               args
  #21 = Utf8               [Ljava/lang/String;
  #22 = Utf8               s1
  #23 = Utf8               Ljava/lang/String;
  #24 = Utf8               s2
  #25 = Utf8               s3
  #26 = Utf8               s4
  #27 = Utf8               s5
  #28 = Utf8               SourceFile
  #29 = Utf8               Demo1_1.java
  #30 = NameAndType        #11:#12        // "<init>":()V
  #31 = Utf8               a
  #32 = Utf8               b
  #33 = Utf8               ab
  #34 = Utf8               java/lang/StringBuilder
  #35 = NameAndType        #39:#40        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #36 = NameAndType        #41:#42        // toString:()Ljava/lang/String;
  #37 = Utf8               com/demo/jvm/Demo1_1
  #38 = Utf8               java/lang/Object
  #39 = Utf8               append
  #40 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #41 = Utf8               toString
  #42 = Utf8               ()Ljava/lang/String;
{
  public com.demo.jvm.Demo1_1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/demo/jvm/Demo1_1;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=6, args_size=1
         0: ldc           #2                  // String a
         2: astore_1
         3: ldc           #3                  // String b
         5: astore_2
         6: ldc           #4                  // String ab
         8: astore_3
         9: new           #5                  // class java/lang/StringBuilder
        12: dup
        13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
        16: aload_1
        17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        20: aload_2
        21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        27: astore        4
        29: ldc           #4                  // String ab
        31: astore        5
        33: return
      LineNumberTable:
        line 5: 0
        line 6: 3
        line 7: 6
        line 8: 9
        line 9: 29
        line 10: 33
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      34     0  args   [Ljava/lang/String;
            3      31     1    s1   Ljava/lang/String;
            6      28     2    s2   Ljava/lang/String;
            9      25     3    s3   Ljava/lang/String;
           29       5     4    s4   Ljava/lang/String;
           33       1     5    s5   Ljava/lang/String;
}
SourceFile: "Demo1_1.java"
1. String s1 = "a"  代码说明

根据虚拟机指令0,解释器执行了运行时常量池里面的#2,这个时候常量池从空值状态变成了存放了一个符号a(这里只是一个符号),然后根据#31 加载字符串对象"a",常量"a" 压入操作栈

接着执行虚拟机指令2,执行astore_1把刚才的字符串对象"a"保存到LocalVariableTable局部变量表中Slot位置1,变量名是s1

最后就是jvm栈中变量名为s1的指向堆内存中的常量池里面的"a"

同理 String s2 = "b" 

最后把字符串对象"b"保存到局部变量表的中位置2,变量名为s2.

2.接下来在看看String s3 = "ab" 代码说明:

这里执行虚拟机指令9,调用new关键字 最后在堆空间创建了一个StringBuilder对象。

执行指令13,调用了init的无参构造函数

执行指令16,调用aload_1,从局部变量表中拿到s1,

执行指令17,调用StringBuilder.append方法,把s1传入方法中,

同理执行20.21,把s2传入方法中

执行24,调用StrinbBuilder.toString方法

执行27,执行 astore 4 ,把toString 转换后的结果存入局部变量表中的4号位置。

通过查看StringBuilder源代码中toString方法,也可以看出是new了一个新的字符串对象。

3.接着看String s5 = "a" + "b"说明

执指令行29,找到的常量池中#4,也就是符号ab,也就是说常量池中如果已经存在要找的字符串,不需要在存放,直接拿来使用即可

执行指令31,存放到局部变量表中位置5

执行33,方法结束

 

小知识点:可以通过调用intern()方法,尝试讲字符串放入常量池中,有则放入,并返回串池中的对象

1.6版本中,如果串池中没有当前放入的常量,则是copy一份放入串池的

String a1 = "a" + "b" ;
String a2 = a.intern();

总结

  • 字符串对象是不可变(包装类也如此)
  • 第一次使用常量池中的符号才变成对象
  • 字符串变量拼接 原理是StringBuilder.append(),编译期间无法确定字符串变量引用的值,运行期才能确定
  • 字符串常量是编译期间就能确定对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值