⑥. 运行时常量池
①. 运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
②. 运行时常量池( Runtime Constant Pool)是方法区的一部分。
③. 常量池表(Constant Pool Table)是Class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
④. 运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用此时不再是常量池中的符号地址了,这里换为真实地址。
(方法区内常量池之中主要存放的两大类常量:字面量和符号引用。
字面量比较接近Java语言层次的常量概念,如文本字符串、被声明为final的常量值等。
而符号引用则属于编译原理方面的概念,包括下面三类常量:
1、类和接口的全限定名
2、字段的名称和描述符
3、方法的名称和描述符)
⑦. 如何证明静态变量存在哪
/** * 《深入理解Java虚拟机》中的案例: * staticObj、instanceObj、localObj存放在哪里? */ public class StaticObjTest { static class Test { static ObjectHolder staticObj = new ObjectHolder(); ObjectHolder instanceObj = new ObjectHolder(); void foo() { ObjectHolder localObj = new ObjectHolder(); System.out.println("done"); } } private static class ObjectHolder { } public static void main(String[] args) { Test test = new StaticObjTest.Test(); test.foo(); } }
①. staticObj随着Test的类型信息存放在方法区,instance0bj 随着Test的对象实例存放在Java堆,localobject则是存放在foo()方法栈帧的局部变量表中
hsdb>scanoops 0x00007f32c7800000 0x00007f32c7b50000 JHSDB_ _TestCase$Obj ectHolder 0x00007f32c7a7c458 JHSDB_ TestCase$Obj ectHolder 0x00007f32c7a7c480 JHSDB_ TestCase$Obj ectHolder 0x00007f32c7a7c490 JHSDB_ TestCase$Obj ectHolder
②. 测试发现:三个对象的数据在内存中的地址都落在Eden区范围内,所以结论:只要是对象实例必然会在Java堆中分配
③. 接着,找到了一个引用该staticObj对象的地方,是在一个java. lang . Class的实例里,并且给出了这个实例的地址,通过Inspector查看该对象实例,可以清楚看到这确实是一个
java.lang.Class类型的对象实例,里面有一个名为staticObj的实例字段:
④. 从《Java 虛拟机规范》所定义的概念模型来看,所有 C1ass 相关的信息都应该存放在方法区之中,但方法区该如何实现,《Java 虚拟机规范》并未做出规定,这就成了一件允许不同虚拟机自己灵活把握的事情。JDK7 及其以后版本的 Hotspot 虚拟机选择把静态变量与类型在 Java 语言一端的映射 C1ass 对象存放在一起,存储于】ava 堆之中,从我们的实验中也明确验证了这一点.