理解归纳方法区和常量池

前言

    方法区用于存储已经被虚拟机加载的类信息(class文件是存入方法区的),常量,静态变量。

    我对方法区的理解其实是个逻辑区,其是在哪里不重要,在堆内外都没关系,对于HotSpot来说,方法区JDK1.7是在永久代,而1.8在元空间(与堆不相连的本地内存)。

    而常量池是方法区的一部分(说的不是很准备)

1. 常量池:

常量池,分为class常量池和运行时常量池,运行时的常量池是属于方法区的一部分,而Class常量池是Class文件中的。


还有一张图来表示方法区中class文件信息包括哪些内容:

    即方法区里的class文件信息包括:魔数,版本号,常量池,类,父类, 接口数组,字段,方法等信息,其中类里又包括字段和方法的信息。(Class结构可以查看 — 类文件结构)

常量池里存储的内容:


2. class文件常量池和方法区中运行时常量池:

    Class文件中的常量池:

        当class文件被Java虚拟机加载进来后存在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量,符号引用其实引用的就是常量池里面的字符串,但符号引用不是直接存储字符串,而是存储字符串在常量池里的索引。

    方法区中运行时常量池(动态性):

        由于class文件中有一项信息是常量池,这部分内容在类加载后进入方法区的运行时常量池存放,在常量池的符号引用有一部分是会被转变为直接引用的,比如说类的静态方法或私有方法,实例构造方法,父类方法,这是因为这些方法不能被重写其他版本,所以能在加载的时候就可以将符号引用转变为直接引用,而其他的一些方法是在这个方法被第一次调用的时候才会将符号引用转变为直接引用的。

        与Class文件一重大特征是具有动态性,Java并非要求常量一定只有编译期才能产生,即并不是先放入class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,也就是String类的intern()方法。

3. 总结:

    运行时常量池是class文件常量池在运行时的表示。    

    运行时常量池里的内容除了是常量池里的内容外(符号引用的索引值是指向运行时常量池的),还将静态常量池里的符号引用转变为直接引用,而且动态常量池里的内容是能动态添加的。例如调用String的intern方法就能将String的值添加到String常量池中,这里String常量池是包含在运行时常量池里的,但在jdk1.8后,将String常量池放到了堆中。

那么,Integer i = 10是在运行时常量池里还是常量池里找呢?

猜你喜欢

转载自blog.csdn.net/jae_wang/article/details/80291402