Java常量池的理解和总结

池化技术的好处

无论是数据库连接池,还是线程池,或者是现在讨论的Java常量池,使用池化技术的目的无非就是为了避免频繁的创建和销毁对象而影响系统性能,

以字符串常量池为例,在编译阶段,就把所有的字符串文字全部放入到Class文件中的常量池中,这样做有两个好处:

  • 节省空间:字符串常量池中的字符串只存在一份
  • 节省运行时间:因为==要比equals更快,这样才比较两个字符串时就可以直接使用==判断两个引用是否相等,而不用使用equals进行逐一字符的比较

1.字符串常量池

存在位置

  • 在JDK6.0及之前版本,存在于方法区中
  • 在JDK7.0中,字符串常量池被移到了堆中,可能是由于方法区的内存不够用了

每一个被虚拟机加载的类都对应一个class常量池和运行时常量池,但是字符串常量在JVM中只存在一份,被所有的类共享


  • 在JDK6.0及之前版本,字符串常量池中存放的都是字符串常量
  • 在JDK7.0中,由于String.intern()方法的改变,字符串常量池中不仅存放字符串常量,而且可以存放堆中字符串对象的引用

2.class常量池

我们写的Java类被编译之后,就会形成一个class文件,class文件中除了包含类的版本、字段、方法、接口等描述信息外,还包括class常量池,用于编译器生成的各种字面量和符号引用

每个class文件都对应着一个class常量池

什么是字面量和符号引用

  • 字面量:字符串文本、基本数据类型的值、final常量
  • 符号引用:类和方法的全限定名、字段的名称和描述符、方法的名称和描述符

3.运行时常量池

运行时常量池存在于方法区中,也就是class常量池被加载到内存中之后的版本,不用之处在于运行时常量池具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,符号引用也可以被解析为直接引用

JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://hadoo666.top/archives/java常量池的理解和总结md