字符串在我们日常中大量使用,我们希望通过字节码层面看看我们定义了字符串变量时候是什么行为。我们拿一段代码进行分析:
public class Jvm1_22 { public static void main(String[] args) { String s1="a"; String s2="b"; String s3="ab"; } }
我们反编译一下:
javap -v Jvm1_22
我们看关键部分的字节码:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=4, 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: return LocalVariableTable: Start Length Slot Name Signature 0 10 0 args [Ljava/lang/String; 3 7 1 s1 Ljava/lang/String; 6 4 2 s2 Ljava/lang/String; 9 1 3 s3 Ljava/lang/String;
ldc #2表示加载2号位置上的变量操作数栈,astore_1表示把操作数栈顶的值写到变量表的一号槽位中,对应LocalVariableTable上slot的1行中,其他的也是类似。
当我们的程序运行时,常量池中的a b ab这种只是常量符号,还没真正生成对应的字符串对象,需要运行加载操作时候,才会真正生成对象,
当执行ldc #2 时,会生成字符串对象"a"
当执行ldc #3 时会生成字符串对象"b",
当执行ldc #4时候才会生成字符串对象"ab",这种对象生成规律上面是懒惰的。
当生成字符串对象"a"时,字符串对象会以"a"为key去查字符串表中,看下有没有这个对象,没有的话把自己存到字符串表中。
字符串 StringTable [“a”,“b”,“ab”]类似 hashtable结构,不能扩容