Java常量池
- 常量池:用于存放编译期间生成的各种字面量和符号引用
- 字面量:由字母数字等构成的字符串或数值常量,如int a = 1中 1就是字面量
- 符号引用:编译原理中的概念;是相对直接引用来说的,主要包括三类常量
- 类和接口的全限定名,
- 字段的名称和描述符
- 方法的名称和描述符
这些常量池现在都是静态信息,只有运行时被加载到内存后,这些符号才有对应的内存地址信息;就变成了运行时常量池,在程序加载或运行时会被转变为直接引用,也就是动态链接;
字符串常量池
字符串的创建和分配耗费高昂的时间和空间代价,影响程序的性能
- JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化
- 为字符串开辟一块常量池,类似于缓冲区
- 创建字符串对象时,首先查询缓冲区是否命中,
- 存在就返回引用,不存在在堆中或者常量池中实例化后放到常量池中(string a = “常量池中”,string a= new String(“先堆后常量池,两份”))
- intern方法:native 方法,调用此方法时,如果池中已经包含等于此对象值的字符串,就返回池中的字符串;否则,将返回的引用指向当前的字符串;1.6版本需要将当前对象复制一份到池中
- 存储位置
1.6之前,有永久代,运行时常量池在永久代中;运行时常量池就包括字符串常量池;
1.7:有永久代,但逐步去永久代;字符串常量池分离到堆中
1.8之后:无永久代,运行时常量池在元空间,字符串依旧在堆中;
设计原理
底层是hotspot的C++实现的,类似一个HashTable,保存的本质是字符串的引用。
String s1 = new String("he") + new String("llo");//问,共创建多少个对象?
两个new String,各自在堆中和常量池中创建两个对象,he + llo 字面量在常量池直接创建一个;共5个对象
常量池的回收
- 因为常量池是放在堆中,所以他的回收和普通对象是一样的,没有其他特别的地方