7.4.4. 运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分。
常量池表(Constant Pool Table)是 Class 文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
字节码中的常量池存放的都是符号引用,链接解析阶段将符号引用转化为直接引用.所以方法区的运行区常量池里面存放的都是直接引用.
运行时常量池,在加载类和接口到虚拟机后,就会创建对应的运行时常量池。
JVM 为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的。
运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了,这里换为真实地址。
运行时常量池,相对于 Class 文件常量池的另一重要特征是:具备动态性。
以String.intern()为例,编译器会将字符串添加到常量池中(StringTable维护),并返回指向该常量的引用
运行时常量池类似于传统编程语言中的符号表(symboltable),但是它所包含的数据却比符号表要更加丰富一些。
当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则 JVM 会抛 OutOfMemoryError 异常。
深入解析动态性:
动态性是运行时常量池可以动态的往里面添加本来没有的信息
而常量池,只能放代码中存在的信息,在编译期间,就确定了,不会再得到更改
运行时常量池,则可以通过代码动态的往里面塞信息。
7.5. 方法区使用举例
public class MethodAreaDemo { public static void main(String args[]) { int x = 500; int y = 100; int a = x / y; int b = 50; System.out.println(a+b); } }
五个本地变量,所以本地变量表尾5. args存在下标为0的位置上
将500放入操作数栈,然后赋值给变量x中,并将x存放到局部变量表中.
将100放入操作数栈,然后赋值给变量y中,并将y存放到局部变量表中.
读取本地变量表下标为1、2的变量,将其放入到操作数栈中(等待运算)
进行除法运算,并将结果存放到操作数栈中。之后将结果赋值给a,并存放到局部变量表中。
将50放入操作数栈,然后赋值给变量b中,并将b存放到局部变量表中.
获取#2(System.out.printlen)的值,并将其放入操作数栈中.
将本地变量表下标为3、4的加入到操作数栈中,并执行加操作运算。
弹出操作数栈中的参数,传入 # 2对应的方法(System.out.println) ,进行打印操作。
执行return指令,结束方法.
图解纠错
程序计数器里面应该保存的是当前执行指令的下一条指令地址.
分析:PC计数器保存的是当前指令的下一条指令地址。当前指令执行完毕,CPU切换到其他线程,执行另外一个线程的指令。 当CPU再次切换回来时,从PC计数器拿到下一条要执行的指令继续进行执行。
(CPU不会执行一半就去执行其他线程的指令)