运行时数据区
从图中可以看到1.8版本的运行时数据区分为两大部分:线程共享和线程私有。
线程共享:分为堆和方法区。
线程私有:分为程序计数器、本地方法栈、java虚拟机栈。
程序计数器
程序计数器指向了当前程序正在执行的字节码的行号。字节码解释器通过改变程序计数器来实现程序按顺序执行。程序的循环、跳转、选择等操作都依靠程序计数器。
在多线程的环境下cup在一个时间片内执行一个程序。所以记录好当前程序执行到了哪里很重要,这里就是通过程序计数器来记录的。
java虚拟机栈
java虚拟机栈控制着java程序中方法的执行操作,每调用一个方法就会创建一个栈帧放入栈中,栈顶就是当前正在执行的方法。
栈帧可由以下几部分组成:局部变量表、操作数栈、动态链接、方法返回地址和一些其他数据。
局部变量表
存放了在编译期知道的各种数据类型和对象引用。
操作数栈
存放了方法执行过程中产生的中间数据,并可用于计算。
动态链接
用于调用其他方法。在字节码文件中,对象方法都是以符号引用形式存在,要想使用就要转换为内存中对应的直接引用。动态链接的作用就是为了将符号引用转换为调用方法的直接引用。
本地方法栈
和虚拟机栈类似,不过本地方法栈面向的方法是本地方法。
堆
几乎所有java的对象都生成在堆中,随着程序的执行,会有越来越多的对象在堆中创建,堆空间满了就会进行垃圾回收。
方法区
方法区是jvm规范中的定义,不同的jvm可以用不同的方法实现,Hotspot虚拟机在1.7之前的方法区是存储在堆中的永久带,1.8后改为了在内存中的元空间了。
方法区主要存储虚拟机加载的类信息、字段信息、方法信息、常量、静态变量等数据。
运行时常量池
运行时常量池是方法区中的一部分。
在class文件中存在着存储字面量和符号引用的常量池,在转换成运行时数据区后常量池就变成了方法区中的运行时常量池。其中包括编译期确认的字符常量,还将字符引用转换为指向内存的直接引用。还具备动态性。
字符串常量池
是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。
JDK1.7 之前,字符串常量池存放在永久代。JDK1.7 字符串常量池和静态变量从永久代移动了 Java 堆中。