大家好,又见面了,我是你们的朋友全栈君。
字符串常量池概述
常量池表(Constant_Pool table)
Class文件中存储所有常量(包括字符串)的table。这是Class文件中的内容,还不是运行时的内容,不要理解它是个池子,其实就是Class文件中的字节码指令。
运行时常量池(Runtime Constant Pool)
JVM内存中方法区的一部分,这是运行时的内容。这部分内容(绝大部分)是随着JVM运行时候,从常量池转化而来,每个Class对应一个运行时常量池。 上一句中说绝大部分是因为:除了 Class中常量池内容,还可能包括动态生成并加入这里的内容。
字符串常量池(String Pool)
字符串常量池与运行时常量池不是一个概念:
- String Pool 是JVM 实例全局共享的全局只有一个,而Runtime Constant Pool 每个类都有一个。
- String Pool 只记录字符串对象,而Runtime Constant Pool 记录各种对象。
- JVM规范要求进入这里的String 实例叫“被驻留的字符串 – interned string”,各个JVM 可以有不同的实现,HotSpot 是设置了一个哈希表 – StringTable 来引用堆中的字符串实例,被引用就是被驻留。
- 字符串池在JDK 1.7 之后存在于Heap 堆中,旧版存在于方法区中
【亨元模式】 其实字符串常量池这个问题涉及到一个设计模式,叫“享元模式”,顾名思义 – – – > 共享元素模式 也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素。 Java中String部分就是根据享元模式设计的,而那个存储元素的地方就叫做“字符串常量池 – String Pool” 【详细分析】 首先, 10 和 “hello” 会在经过javac(或者其他编译器)编译过后变为Class文件中constant_pool table 的内容,当我们的程序运行时,也就是说JVM运行时,每个Class constant_pool table 中的内容会被加载到JVM内存中的方法区中各自Class的 Runtime Constant Pool. 一个没有被String Pool包含的Runtime Constant Pool中的字符串(这里是”hello”)会被加入到 String Pool中(HosSpot使用hashtable引用方式),步骤如下:
- 在Java Heap(堆)中根据”hello”字面量create一个字符串对象
- 将字面量”hello”与字符串对象的引用在hashtable中关联起来 键 – 值 形式是:“hello” = 对象的引用地址。 另外来说,当一个新的字符串出现在Runtime Constant Pool中时怎么判断需不需要在Java Heap中创建新对象呢? 是这样: 会先去根据equals来比较Runtime Constant Pool中的这个字符串是否和String Pool中某 一个是相等的(也就是找是否已经存在),如果有那么就不创建,直接通过哈希表键值找到对应地址,使用其引用; 如此,就实现了享元模式,提高的内存利用效率。 举例:
int x = 10; String y = "hello";
使用
代码语言:javascript复制String s = new String("hello");
会创建几个对象 答:会创建2个对象 首先,出现了字面量”hello”,那么去String Pool中查找是否有相同字符串存在,因为程序就这一行 代码所以肯定没有,那么就在Java Heap中用字面量”hello”首先创建1个String对象。 接着,new String(“hello”),关键字new又在Java Heap中创建了1个对象,然后调用接收String 参数的构造器进行了初始化。最终s的引用是这个String对象
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/164781.html原文链接:https://javaforall.cn