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个对象

java数字常量类工具 java数字常量池_常量池

常量池的回收

  • 因为常量池是放在堆中,所以他的回收和普通对象是一样的,没有其他特别的地方