`

JVM对String常量表达式的处理和优化

    博客分类:
  • JVM
 
阅读更多
1.看看下面这段代码执行结果是什么?
String a = "ab";
String b = "a" + "b";
System.out.println((a == b));  //它的执行结果为true;

2.下面这段代码的执行结果是什么?
String a = "ab";
String bb = "b";
String b = "a" + bb;
System.out.println((a == b));   //执行结果为false

以上两个执行结果的原因分析:
    String b = "a" + "b";编译器将这个"a" + "b"作为常量表达式,在编译时进行优化,直接取结果"ab",这样这个问题退化
    String a = "ab";
    String b = "ab";
    System.out.println((a == b));
    然后根据3的解释,得到结果true

javap工具执行查看字节码如下:

0:   ldc     #16; //String ab

2:   astore_1

3:   ldc     #16; //String ab

5:   astore_2

6:   getstatic       #18; //Field java/lang/System.out:Ljava/io/PrintStream;

9:   aload_1

10:  aload_2

11:  if_acmpne       18

14:  iconst_1

15:  goto    19

18:  iconst_0

19:  invokevirtual   #24; //Method java/io/PrintStream.println:(Z)V

22:  return

通过 0:   ldc     #16; //String ab和 3:   ldc     #16; //String ab ,知道该java文件通过编译器编译后都变为    String b = "ab"; 和作者分析的一样。

===========================
对于第二个程序这个好理解,"a" + bb中的bb是变量,不能进行优化。javap查看字节码如下:
0:   ldc     #16; //String ab

   2:   astore_1

   3:   ldc     #18; //String b

   5:   astore_2

   6:   new     #20; //class java/lang/StringBuilder

   9:   dup

   10:  ldc     #22; //String a

   12:  invokespecial   #24; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V

   15:  aload_2

   16:  invokevirtual   #27; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

   19:  invokevirtual   #31; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

   22:  astore_3

   23:  getstatic       #35; //Field java/lang/System.out:Ljava/io/PrintStream;

   26:  aload_1

   27:  aload_3

   28:  if_acmpne       35

   31:  iconst_1

   32:  goto    36

   35:  iconst_0

   36:  invokevirtual   #41; //Method java/io/PrintStream.println:(Z)V

   39:  return


String+String的操作是在运行时进行的,则会产生新的对象,而不是直接从jvm的string池中获取。


===============================
再看下面两个例子:

String a = "ab";
final String bb = "b";
String b = "a" + bb;
System.out.println((a == b));   //result = true


String a = "ab";
final String bb = getBB();
String b = "a" + bb;
System.out.println((a == b));    //result = false
private static String getBB() {
return "b";
}


查看下面的字节码如下:
  0:   ldc     #16; //String ab

   2:   astore_1

   3:   invokestatic    #18; //Method getBB:()Ljava/lang/String;

   6:   astore_2

   7:   new     #22; //class java/lang/StringBuilder

   10:  dup

   11:  ldc     #24; //String a

   13:  invokespecial   #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V

   16:  aload_2

   17:  invokevirtual   #29; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

   20:  invokevirtual   #33; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

   23:  astore_3

   24:  getstatic       #36; //Field java/lang/System.out:Ljava/io/PrintStream;

   27:  aload_1

   28:  aload_3

   29:  if_acmpne       36

   32:  iconst_1

   33:  goto    37

   36:  iconst_0

   37:  invokevirtual   #42; //Method java/io/PrintStream.println:(Z)V

   40:  return


  分析:0:   ldc     #16; //String ab 变量a的值直接指向常量池中的‘ab’,

   通过下面的分析可知 变量2通过StringBuilder进行string操作。











分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics