原文地址:深入理解JVM(三)-JVM中的常量池
JVM的常量池主要有以下几种:
- 运行时常量池
- 字符串常量池
- 基本类型包装类常量池
- class文件常量池
他们之间的关系:
图解说明:
-
每个class的字节码文件中都有一个常量池,里面是编译后即知的该class会用到的字面量与符号引用,这就是class文件常量池。JVM加载class,会将其类信息,包括class文件常量池置于方法区中。
-
class类信息及其class文件常量池是字节码的二进制流,它代表的是一个类的静态存储结构,JVM加载类时,需要将其转换为方法区中的java.lang.Class类的对象实例;同时,会将class文件常量池中的内容导入运行时常量池。
-
运行时常量池中的常量对应的内容只是字面量,比如一个"字符串",它还不是String对象;当Java程序在运行时执行到这个"字符串"字面量时,会去字符串常量池里找该字面量的对象引用是否存在,存在则直接返回该引用,不存在则在Java堆里创建该字面量对应的String对象,并将其引用置于字符串常量池中,然后返回该引用。
-
Java的基本数据类型中,除了两个浮点数类型(Float、Double),其他的基本数据类型都在各自内部实现了常量池,但都在[-128~127]这个范围内。
class文件常量池
首先我们通过一个简单的类来了解class文件常量池
package com.mazai.learning.jvm;
public class Student {
private final String name = "张三";
private final int entranceAge = 18;
private String evaluate = "优秀";
private int scores = 95;
private Integer level = 5;
public String getEvaluate() {
return evaluate;
}
public void setEvaluate(String evaluate) {
String tmp = "+";
this.evaluate = evaluate + tmp;
}
public int getScores() {
return scores;
}
public void setScores(int scores) {
final int base = 10;
System.out.println("base:" + base);
this.scores = scores + base;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
}
使用反编译命令:javap -verbose Student.class
Classfile /D:/ideaspace/mazai-learning/mazai-jvm/target/classes/com/mazai/learning/jvm/Student.class
Last modified 2022-9-27; size 1581 bytes
MD5 checksum 361fea8d9e4c6966a3a2b295310f3a18
Compiled from "Student.java"
public class com.mazai.learning.jvm.Student
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #19.#53 // java/lang/Object.&#