从字节码看String-阿里云开发者社区

开发者社区> 茕祇> 正文

从字节码看String

简介: 从字节码看String
+关注继续查看

从一道很古老的面试题说起

public class TestString {
    public static void main(String[] args) throws InterruptedException {
        String a = new String("abc");
        String b = new String("abc");
    }
}

一般都会这么问,在执行String a = new String("abc");String b = new String("abc");这两句代码的时候,会创建几个对象,按照网上流传的方法分析的话,大概是3个,先将一个"abc"字面量(String litera)放入常量池中,然后创建两个String对象,指向这个字符串常量,我们知道,在字节码中,能够数组的指令有newarray,anewarray,multianewarray,但创建一个类实例的指令只有new.

我们拿出这段代码的字节码形态

image-20211021170721026

只有两个new指令,根据对称性很容易看出来,0-9是第一行代码,10-19是第二行代码,而关于我们所说的字符串字面量却并没有在这里被创建,而只是从常量池中通过ldc加载过来,也就是说,如果单纯的只说这两行代码的执行阶段创建了几个对象,应该说只创建了两个,但是如果说涉及了几个对象,那当然还是三个.

编译期优化

我们再来看一段代码

String a = "a";
String ab = a+"b";

我们知道,若是"a"+"b"那么在编译的时候就会自动优化为"ab",但如果是a+"b"则不会如此,为什么呢?笔者认为,之所以前者可以被优化,是因为在编译期是已知的,但换做引用就说不准了,不运行,就不会知道最终所引用的对象是什么样子的,因此不能如此优化.那这里可以说创建了几个对象呢? 我们说,有几个new,就创建了几个对象,这里创建了一个StringBuilder,以及一个String对象,但这里只有一个new,另一个new在那个toString方法中.

image-20211021180836733

与之作为对比将a声明为final

final String a = "a";
String ab = a+"b";

则可以在编译期完成优化,字节码如下

image-20211021182046404

StringBuilder创建

再让我们回到前一份字节码,可以验证a+"b"的这个连接操作实质上确实如网上所说是通过一个StringBuilder实例来完成的.

我们再通过字节码来验证应该自己手动创建StringBuilder这句话的正确性

String c = "";
for(int i =1;i<4;i++){
        c+=i;
}

image-20211021183256964

图中红色区域即为循环体,可以看到,隐式使用StringBuilder是会在每次迭代时都创建一个新的实例,因此会导致效率降低.

但值得注意的是,在java11中,就不是采用的StringBuilder了,而是StringConcatFactory.makeConcatWithConstants()

java11的版本下获取的字节码如下,可以看出,这里不再存在StringBuilder,而换成了 invokedynamic #3 <makeConcatWithConstants, BootstrapMethods #0>

image-20211021185141436

关于String还有一个重要的方法就是intern,若字符串常量池中能找到这个字符串字面量,则返回该字面量地址,否则则把此

时的String对象放入常量池,并返回其地址.关于这个方法的验证,字节码就无能为力了,我们得从内存以及jvm源码去分析

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
org.apache.tomcat.util.scan.StandardJarScanner找不到serializer.jar的问题
org.apache.tomcat.util.scan.StandardJarScanner找不到serializer.jar的问题
6 0
如何在JSP里使用Java bean
如何在JSP里使用Java bean
5 0
如何在JSP里自定义标签
如何在JSP里自定义标签
5 0
JSP里的System.out.println
JSP里的System.out.println
4 0
Tomcat服务器java.lang.IllegalArgumentException异常
Tomcat服务器java.lang.IllegalArgumentException异常
4 0
package javax.servlet.jsp.tagext does not exist的错误消息如何解决
package javax.servlet.jsp.tagext does not exist的错误消息如何解决
6 0
jsp项目手动导出成war包
jsp项目手动导出成war包
5 0
利用JSP内置的Application对象实现的网站引用计数
利用JSP内置的Application对象实现的网站引用计数
7 0
java.lang.ClassNotFoundException org.w3c.dom.ElementTraversal
java.lang.ClassNotFoundException org.w3c.dom.ElementTraversal
5 0
+关注
7
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载