Java虚拟机的静态常量池和运行时常量池

静态)常量池:用于存放编译器生成的各种字面量和符号引用(符号引用区别于直接引用,后者在class字节码文件被虚拟机解析之后,符号引用将被替换为直接引用)。

运行时常量池:(静态)常量池中的内容在类加载(这里的类加载指class字节码文件经过加载连接初始化的过程)后存放入方法区的运行时常量池中。相对于静态常量池,运行时常量池具有动态性,在程序运行的时候可能将新的常量放入运行时常量池中,比如使用String类的intern方法。

对静态常量池直观的理解,它是编译器编译java代码之后所产生的常量,这里的常量跟编写代码的常量不同,指的是类、接口、方法和字段的描述信息,比如类的名称和其基类。“静态”,是因为它们只是一个class的描述信息而已,还没有具备被执行的能力。在该class文件被JVM装载完成之后,静态常量池中的内容将被解析,并放到运行时常量池中。动态常量池和静态常量池可以类比程序和进程的关系。

运行时常量池包含:

类、接口、方法和类字段的表述信息
字符串常量池
被final所修饰的类变量
自动包装类Byte,Short,Integer,Long,Character在-128到127之间值。
方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译之后的代码等数据。

按照这样的理解,因为静态常量池中的内容只是编译之后的产物,所以其不保存在方法区中。

这便是(静态)常量池和动态常量池的区别

Java静态常量池和运行时常量池

Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。

所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。
而运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。
运行时常量池相对于Class文件常量池的另外一个重要特征就是具备动态性,Java语言并不要求常量一定只有在编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法.其中intern()方法描述如下:

既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。