c++ 返回string_JVM系列之:String.intern和stringTable

4e193e0a8ce38f1e392eedf60dc22b11.png

简介

StringTable是什么?它和String.intern有什么关系呢?在字符串对象的创建过程中,StringTable有起到了什么作用呢?

一切的答案都在本文中,快来看看吧。

intern简介

intern是String类中的一个native方法,所以它底层是用c++来实现的。感兴趣的同学可以去查看下JVM的源码了解更多的内容。

这里我们主要谈一下intern的作用。

intern返回的是这个String所代表的对象,怎么理解呢?

String class维护了一个私有的String pool, 这个String pool也叫StringTable,中文名字叫做字符串常量池。

当我们调用intern方法的时候,如果这个StringTable中已经包含了一个相同的String对象(根据equals(Object)方法来判断两个String对象是否相等),那么将会直接返回保存在这个StringTable中的String。

如果StringTable中没有相同的对象,那么这个String对象将会被加入StringTable,并返回这个String对象的引用。

所以,当且仅当 s.equals(t) 的时候s.intern() == t.intern()。

intern和字符串字面量常量

我们知道在类文件被编译成class文件时,每个class文件都有一个常量池,常量池中存了些什么东西呢?

字符串常量,类和接口名字,字段名,和其他一些在class中引用的常量。

看一个非常简单的java类:

public class SimpleString {public String site="www.flydean.com";
}

然后看一下编译出来的class文件中的Constant Pool:

Constant pool:#1 = Methodref          #2.#3          // java/lang/Object."<init>":()V#2 = Class              #4             // java/lang/Object#3 = NameAndType        #5:#6          // "<init>":()V#4 = Utf8               java/lang/Object#5 = Utf8               <init>#6 = Utf8               ()V#7 = String             #8             // www.flydean.com#8 = Utf8               www.flydean.com#9 = Fieldref           #10.#11        // com/flydean/SimpleString.site:Ljava/lang/String;#10 = Class              #12            // com/flydean/SimpleString#11 = NameAndType        #13:#14        // site:Ljava/lang/String;#12 = Utf8               com/flydean/SimpleString#13 = Utf8               site#14 = Utf8               Ljava/lang/String;#15 = Utf8               Code#16 = Utf8               LineNumberTable#17 = Utf8               LocalVariableTable#18 = Utf8               this#19 = Utf8               Lcom/flydean/SimpleString;#20 = Utf8               SourceFile#21 = Utf8               SimpleString.java

上面的结果,我们可以看到class常量池中的index 7存放了一个字符串,这个字符串的实际内容存放在index 8中,是一个变种的Utf8的编码。

#7 = String             #8             // www.flydean.com#8 = Utf8               www.flydean.com

好了,现在问题来了,class文件中的常量池在运行时需要转换成为JVM能够识别的运行时常量池,这个运行时的常量池和StringTable和intern有什么关系呢?

9200caca490d9f6c5c0f638eda446ed2.png

在java对象的实例化过程中,所有的字符串字面量都会在实例化的时候自动调用intern方法。

如果是第一次调用,则会创建新的String对象,存放在String Table中,并返回该String对象的引用。

分析intern返回的String对象

从上面的图中,我们也可以出来String Table中存储的是一个String对象,它和普通的String对象没有什么区别,也分为对象头,底层的byte数组引用,int hash值等。

如果你不相信,可以使用JOL来进行分析:

log.info("{}", ClassLayout.parseInstance("www.flydean.com".intern()).toPrintable());

看下输出结果:

INFO com.flydean.StringInternJOL - java.lang.String object internals:OFFSET  SIZE      TYPE DESCRIPTION                               VALUE0     4           (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)4     4           (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)8     4           (object header)                           77 1a 06 00 (01110111 00011010 00000110 00000000) (399991)12     4    byte[] String.value                              [119, 119, 119, 46, 102, 108, 121, 100, 101, 97, 110, 46, 99, 111, 109]16     4       int String.hash                               020     1      byte String.coder                              021     1   boolean String.hashIsZero                         false22     2           (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 2 bytes external = 2 bytes total

分析实际的问题

有了上面的知识,让我们分析一下下面的实际问题吧:

String a =new String(new char[]{'a','b','c'});String b = a.intern();System.out.println(a == b);String x =new String("def");String y = x.intern();System.out.println(x == y);

两个很简单的例子,答案是什么呢? 答案是true和false。

第一个例子按照上面的原理很好理解,在构建String a的时候,String table中并没有”abc“这个字符串实例。所以intern方法会将该对象添加到String table中,并返回该对象的引用。

所以a和b其实是一个对象,返回true。

那么第二个例子呢?初始化String的时候,不是也没有”def“这个字符串吗?为什么回返回false呢?

还记得我们上面一个小节分析的吗?所有的字符串字面量在初始化的时候会默认调用intern方法。

也就是说”def“在初始化的时候,已经调用了一次intern了,这个时候String table中已经有”def“这个String了。

所以x和y是两个不同的对象,返回的是false。

注意,上面的例子是在JDK7+之后运行的,如果你是在JDK6中运行,那么得到的结果都是false。

JDK6和JDK7有什么不同呢?

在JDK6中,StringTable是存放在方法区中的,而方法区是放在永久代中的。每次调用intern方法,如果String Table中不存在该String对象,则会将该String对象进行一次拷贝,并返回拷贝后String对象的引用。

因为做了一次拷贝,所以引用的不是同一个对象了。结果为false。

在JDK7之后,StringTable已经被转移到了java Heap中了,调用intern方法的时候,StringTable可以直接将该String对象加入StringTable,从而指向的是同一个对象。

G1中的去重功能

如果频繁的进行String的复制,实际上是非常消耗内存空间的。所以在G1垃圾回收器中,可以使用下面的:

-XX:+UseStringDeduplication

来开启String的去重功能。

我们还记得String对象的底层结构吧,就是一个byte[]数组,String去重的原理就是让多个字符串对象底层的byte数组指向同一个地方。从而节省内存。

我们可以通过使用:

-XX:+PrintStringTableStatistics

参数来查看StringTable的大小。并通过:

-XX:StringTableSizen=n

来指定StringTable的大小。

总结

本文讲了String.intern和String table的关系,如果有什么错误或者遗漏的地方,欢迎大家留言给我!

本文作者:flydean程序那些事本文链接:http://www.flydean.com/jvm-string-intern/本文来源:flydean的博客欢迎关注我的公众号:程序那些事,更多精彩等着您!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/534050.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

conda install 换源_ubuntu更换pip install,apt-get,conda install 成国内源

# 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe mu…

python帮助文档中查看内置函数_PYTHON官方文档内置函数整理

一、数学运算类 abs(x) 求绝对值 1 、参数可以是整型&#xff0c;也可以是复数 2 、若参数是复数&#xff0c;则返回复数的模 complex([real[, imag]]) 创建一个复数 divmod(a, b) 分别取商和余数 注意&#xff1a;整型、浮点型都可以 float([x]) 将一个字符串或数转换为浮点数…

计算机二级指针,C语言——二级指针

二级指针的概念首先任何值都有地址&#xff0c;一级指针的值虽然是地址&#xff0c;但这个地址做为一个值亦需要空间来存放&#xff0c;是空间就具有地址&#xff0c;这就是存放地址这一值的空间所具有的地址&#xff0c;二级指针就是为了获取这个地址&#xff0c;一级指针所关…

华为 虚拟键盘_华为mate30 pro虚拟机械键盘特有体验,虽是虚拟,但却感受逼真...

华为Mate30 pro已于26日在国内正式发布了。此外&#xff0c;根据了解华为Mate30系列现在已经突破了5亿的销售额。看来&#xff0c;华为的这个下半年旗舰手机非常受欢迎啊。华为Mate30系列现在在国内已经发布了&#xff0c;其整体感官看上去与海外的没有多大的区别。其实&#x…

python 如何快速判断列表是否相同_Python-检查列表中的所有元素是否相同

小编典典 通用方法&#xff1a; def checkEqual1(iterator): iterator iter(iterator) try: first next(iterator) except StopIteration: return True return all(first rest for rest in iterator) 单线&#xff1a; def checkEqual2(iterator): return len(set(iterator)…

计算机有什么著名基金经理排名,百万年薪的基金经理,都是什么专业出身?!...

有人会说了“小哔君你四不四撒&#xff01;基金经理肯定是金融专业出身的咯&#xff1f;不然嘞&#xff1f;”但事实的真相是许多基金经理都并非科班出身这要从基金经理的晋升机制说起了&#xff01;如下图基金经理都是从研究员做起的&#xff01;那么问题来了&#xff0c;如何…

遍历children_589. N叉树的前序遍历

589. N叉树的前序遍历给定一个 N 叉树&#xff0c;返回其节点值的前序遍历。例如&#xff0c;给定一个 3叉树 :返回其前序遍历: [1,3,5,6,2,4]。说明: 递归法很简单&#xff0c;你可以使用迭代法完成此题吗?题解&#xff1a;既然是树的遍历&#xff0c;那么一共就是两种思路&a…

计算机护理职称考试报名时间2015,护理职称考试怎么报名?

护理职称考试报名流程&#xff1a;网上预报名-现场确认-报名缴费。护理职称考试网上预报名及网上缴费均在中国卫生人才网&#xff0c;护理职称考试报名现场确认则按属地原则在单位或户籍所在地的卫计局。护理职称考试报名流程详解一、网上预报名考生需在规定的时间内登录中国卫…

怎么用python编程前二n-1项的等差数列的和_python 等差数列末项计算方式

等差数列末项计算 题目内容&#xff1a; 给出一个等差数列的前两项a1&#xff0c;a2&#xff0c;求第n项是多少 可以使用以下语句实现非负整数n的输入&#xff1a; nint(input()) 输入格式: 三行&#xff0c;包含三个整数a1&#xff0c;a2&#xff0c;n 输出格式&#xff1a; 一…

图纸中bs是什么意思_园建施工图中WL、BL、FL、TW、SL分别是什么意思

展开全部WL是水面标高来BL池底自标高FL地面标bai高TW墙顶标高SL 土面标高其他其他一些常du用的注解&#xff1a;PA种植区FF室内楼zhi地面标FG室外软景完成dao面标高BC路沿底标高BS踏步底标高BR栏杆扶手底标高TR栏杆扶手顶标高SL结构板顶标高扩展资料本书围绕园林工程建设主题&a…

计算机未显示移动硬盘,电脑不显示移动硬盘怎么办_移动硬盘已连接不显示解决教程...

最近有很多小伙伴咨询小编&#xff0c;电脑不显示移动硬盘怎么办&#xff0c;怎么设置才能恢复呢&#xff1f;其实操作内容很简单&#xff0c;尝试删除你的USB3.0可扩展主机控制器,再扫描硬件改动&#xff0c;今天就由小编来告诉你&#xff0c;移动硬盘已连接不显示的解决方法。…

八个角最多可以把平面分成多少部分?_一个空间最多能被分成几块?

相信大家在小学奥数中都遇到这样一个问题&#xff1a;4条直线最多能将平面分成几部分&#xff1f;这个问题并不能难倒我们&#xff0c;但是如果将问题改为&#xff1a;4个平面最多能将空间分为几部分&#xff1f;这下子我们可能就要放弃了。为了解决这个问题&#xff0c;今天我…

ios 不被遮挡 阴影_IOS开发之Bug--iOS7View被导航栏遮挡问题的解决

在实际开发中&#xff0c;遇到在UITextView的frame等于当前控制器的View的frame的情况下&#xff0c;然后运行的时候&#xff0c;发现控制器的Frame的高度y值会从导航条的位置64变化到0。导致UITextView的frame也跟着一起移动。这个问题本质其实就是iOS7View被导航栏遮挡问题&a…

破坏计算机信息系统功能罪,破坏计算机信息系统罪

破坏计算机信息系统罪2010年05月05日19:42法律咨询 我要评论一、概念&nbsp&nbsp&nbsp&nbsp破坏计算机信息系统罪(刑法第286条)&#xff0c;是指违反国家规定&#xff0c;对计算机信息系统功能或计算机信息系统中存储、处理或者传输的数据和应用程序进行破坏…

python解析html xml最好的模块_Python HTML/XML解析器BeautifulSoup(爬虫解析器)

The Dormouses storyOnce upon a time there were three little sisters; and their names were Elsie, Lacie and Tillie; and they lived at the bottom of a well....

ffmpeg运行在服务器上,FFMPEG安装在服务器上

我有一个在线服务器(共享主机方案)在Linux中&#xff0c;我不知道很多关于Linux的东西&#xff0c;我正在尝试安装ffmpeg。FFMPEG安装在服务器上当安装正在运行我得到这个消息&#xff0c;并停止安装...Installation of MPlayer-1.0rc1.tar.bz2 ....... started% Total % Recei…

python csv pandas_Python Pandas——Read_csv详解

目前最常用的数据保存格式可能就是CSV格式了&#xff0c;数据分析第一步就是获取数据&#xff0c;怎样读取数据至关重要。 本文将以pandas read_csv方法为例&#xff0c;详细介绍read_csv数据读取方法。再数据读取时进行数据预处理&#xff0c;这样不仅可以加快读取速度&#x…

python3兼容python2 print_python 字符串 r raw Python2 和 Python3 的区别及兼容技巧

前言最近 Python 之父 Guido van Rossum(龟爷)终于在 Python 官方邮件组落实了 Python 2.7 的终焉之日(EOL)。说的是 Python 2.7 的 EOL 日期最终确定为 2020 年 1 月 1 日&#xff0c;之后不会有任何更新&#xff0c;包括源码的安全补丁。所以兼容Python3已经可以说非常必要了…

nginx搭建文件服务器脚本,基于docker搭建nginx文件服务器的方法步骤

1.在本机新建配置文件docker_nginx.confserver {listen 7070;server_name localhost;charset utf-8;location /files {#在docker内nginx的目录alias /home/files;expires 1d;allow all;autoindex on;}2.启动命令docker run --name nginx -d -p 7070:7070 -v D:\dev\nginx-1.13.…

python运行不了指令_python不是内部命令或外部命令,也不是可执行程序解决方法...

简述 常见于新手初装python&#xff0c;然后忘记勾选设置环境变量(PATH)&#xff0c;或者没有重启&#xff0c;然后运行教程中的python命令时出现。 有两个解决方法&#xff1a;1.设置环境变量&#xff0c;然后重启。 2.新建命令。 如果你打算同时安装多个python版本&#xff0…