首页 > 其他分享 >JVM-字符串底层实现原理

JVM-字符串底层实现原理

时间:2023-01-28 21:32:54浏览次数:41  
标签:字节 StringBuilder 拼接 toString 指令 JVM 字符串 底层


1.什么字符串会进入字符串常量池

1. 直接写的字面量

2. 字面量的拼接结果(注意:如果字符串拼接中有变量则结果不会进入字符串常量池)

3. 调用String的intern方法可以将String存入字符串常量池

2. 字面量的拼接原理

有如下列展示代码:

JVM-字符串底层实现原理_字符串

在ideal中查看编译的class文件:

JVM-字符串底层实现原理_java_02

总结:

以上面两个文件我们可以看出,这种字符串的拼接在编译期间就已经优化了,直接就合并为一个字符串;并且这个字符串存放在字符串常量池

3. 字符串和变量拼接原理

java源码:

JVM-字符串底层实现原理_jvm_03

利用jclasslib查看main方法的字节码命令:

如果以下名词不明白请阅读请自行了解学习java虚拟机栈;

我们可以发现就简单的两行代码,产生了这么多的字节码命令;

在代码中我简单解释了每一行的作用。

JVM-字符串底层实现原理_java_04

总结:

以上内容我们可以知道字符串拼接实际上就是创建了一个StringBuilder对象然后向里面append内容,最后调用toString方法获得结果

3.1 为什么结果没有存储在常量池

从上述字节码指令已经知道了字符串拼接结果是StringBuilder的toString方法的结果,那么 toString里面具体做了什么事情,又是为什么结果不在常量池?

以下StringBuilder.toString的源码以及字节码指令:

JVM-字符串底层实现原理_java_05

总结:

以上代码可以很好的解释实际上最终是调用了的构造方法传入一个数组,那么最终的结果肯定也就在咱们的堆空间。

4. 为什么字符串拼接效率低

4.1. 源码准备

首先编写两个方法一个使用字符串拼接,一个使用StringBuilder进行拼接

JVM-字符串底层实现原理_字符串_06

4.2.字节码指令层面解析

以上代码的执行时间长短我就不在重复测试了相信大家都会,接下来我们来一起看看这两个方法字节码指令。

concatStrByDefault方法的字节码指令如下:

简单解释下循环是在33行的goto指令调到第5行这样不断循环;并且在11行也就是循环中不断的通

过new创建了StringBuilder对象,也就是循环了多少次就创建了多少个StringBuilder对象,并且如果大家看了我之前写字符串拼接原理,在StringBuilder的toString方法中还new 了一个String对象;这里这么多对象的创建就必然需要垃圾回收效率自然就低了

JVM-字符串底层实现原理_java_07

concatStrByBuilder方法的字节码指令:

此处循环在27行的goto指令跳到12行,并且循环之间是没有创建新对象的,紧紧只是调用了 append方法,这里就能很明显的看出这种方式比普通拼接少创建了很多的对象

JVM-字符串底层实现原理_java_08

4.3. 总结

拼接效率低的主要原因也就是每一次拼接都创建了一个StringBuilder对象,并且在赋值是又需要调用toString方法,而toString方法的实现里面有new了一个String对象,所以拼接的效率很低。

标签:字节,StringBuilder,拼接,toString,指令,JVM,字符串,底层
From: https://blog.51cto.com/u_8238263/6025163

相关文章

  • JVM垃圾回收
    一、如何判断对象可以回收?1.引用计数法:只要一个对象被其他变量所引用,就让计数加一,引用两次就让计数变为2,取消引用就让计数减一,但是这种算法有严重的弊端,如果两个变量......
  • Oracle in 无法处理字符串
    在OracleSQL中,有时候需要用到条件Select*fromTwhere条件字段in(A,B),而大多数情况下in后面的条件是在数据库外部获取的字符串形式,这时候就需要换一种写法:Selec......
  • bzip2库bzlib.h使用(三):底层接口
    说明bzip2提供了底层接口、高级接口以及两个实用函数(Utilityfunctions)。本文的主要目的,是说明如何使用底层接口解压数据。底层接口可以控制每次解压的数量,常用在对内存......
  • 代码随想录算法训练营第十一天 | 20. 有效的括号,1047. 删除字符串中的所有相邻重复项,1
    一、参考资料有效的括号题目链接/文章讲解/视频讲解:https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html删除字符串中的所有相邻......
  • MySQL索引底层探究
    一、什么是索引?索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。索引是一种数据结构。数据库索引,是数据库......
  • Oracle根据符号分隔字段内字符串后SQL查询数据方法
    --从WITH函数子查询中获取需要的数据SELECTCOUNT(*)FROMCT_BC_BUSINESSCARDFLOWt1WHEREt1.CFSerialNumberNOTIN(--利用WITH函数实现子查询(当做内联视图或者临......
  • day11-实现Spring底层机制-01
    实现Spring底层机制-01主要实现:初始化IOC容器+依赖注入+BeanPostProcessor机制+AOP前面我们实际上已经使用代码简单实现了:SpringXML注入bean(Spring基本介绍02)Sp......
  • Python字符串
    1.replace替换#replace实现字符串替换a='sjbfnjajjkdgbnv'a=a.replace('f','里')print(a)out:sjb里njajjkdgbnv整个过程,实际是创建了新的字符串对象,并指向了变量a,并......
  • STM32-USART打印字符、字符串函数自己犯的错误反思
    voidUART_Send_Byte(USART_TypeDef*USARTx,uint8_tcha){ USART_SendData(USARTx,cha); while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);}其......
  • HashMap和HashTable的区别,其底层原理
    区别:HashMap中允许存在null的键和值,但HashTable不允许HashTable中每个方法都有synchronized修饰,所以HashTable是线程安全的,而HashMap不是。但多线程情况下仍然不建议使......