文章目录
  1. 1. Java运行时数据区域划分
  2. 2. 程序计数器
  3. 3. Java虚拟机栈和本地方法栈
    1. 3.1. Java虚拟机栈
    2. 3.2. 本地方法栈
  4. 4. Java堆
  5. 5. 方法区
    1. 5.1. 运行时常量池

  Java虚拟机在执行Java程序的过程中会将其管理的内存分为多个不同的区域,了解这些区域,有助于编码时规避和排查一些内存管理的错误。

Java运行时数据区域划分

  在《Java虚拟机规范》中,对于运行时数据区域有以下划分,但在具体的不同虚拟机的实现中,可能有所不同,本文将整理最基本的划分情况,同时会涉及到目前应用最广泛的虚拟机——HotSpot虚拟机中的使用情况。
  首先给出Java虚拟机运行时数据区的划分情况图:


Java虚拟机运行时数据区

  如上图所示,虚拟机将运行时数据区分为五块,其中由所有线程共享的区域有:方法区、堆;线程隔离的数据区有:虚拟机栈、本地方法栈、程序计数器。在HotSpot虚拟机中,将虚拟机栈和本地方法栈合二为一,因此HotSpot虚拟机的运行时数据区共有四块。以下分别介绍各个区域的概况。

程序计数器

  程序计数器为线程私有,该区域是一块较小的内存空间,指示了当前线程所执行的字节码行号。若正在执行Java方法,则该计数器执行的是正在执行的虚拟机字节码指令地址;若正在执行Native方法,则该计数器为空(Undifined)。

Java虚拟机栈和本地方法栈

Java虚拟机栈

  Java虚拟机栈为线程私有,其生命周期与线程相同。它存储了一个个栈帧(Stack Frame),每个方法在执行时都会创建一栈帧,栈帧中存储了:局部变量表、操作数栈、动态链接、方法出口(即返回地址)等信息。
  人们常说的栈内存(Stack),严格来说就是指的虚拟机栈栈帧中的局部变量表部分,在上图中已用红色方框进行了标注。局部变量表存储了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、dobule)、对象引用(reference类型)和returnAddress类型的数据。
  在局部变量表中存储数据的单位是变量槽(Variable Slot,简称Slot),其中64位长度的longdouble类型的数据占用2个Slot,其它类型的数据占据1个Slot。局部变量表所需的内存在编译期间完成分配,运行期间不会改变它的大小。

本地方法栈

  本地方法栈与Java虚拟机栈作用相似,区别在于Java虚拟机栈为执行Java方法(即字节码)服务,而本地方法栈为执行Native方法服务。那么什么是Native方法呢?简单来说,一个Native方法就是一个Java调用非Java代码的接口,Native方法一般由非Java语言实现,如C或者C++。
  在HotSpot虚拟机中,本地方法栈和虚拟机栈是合二为一的,在上图中笔者用蓝色方框进行了标注。

Java堆

  Java堆就是人们常说的堆内存(Heap),该内存是线程共享的,其生命周期与虚拟机的启动和关闭相同。该内存的唯一目的就是存放对象实例,它是垃圾收集器管理的主要区域。
  在HotSpot虚拟机中,从内存回收的角度来看,Java堆又分为新生代(Young Generation)老年代(Tenured Generation),回收新生代的算法为复制算法,再该算法中,又将新生代分为一块较大的Eden空间和两块较小的From Suvivor空间To Survivor空间;回收老年代的算法为标记-整理算法标记-清除算法

方法区

  方法区是线程共享的,它存储了类数据,包括:类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区有一个别名叫非堆(Non-Heap),在上图中已经用红色的字标注。
&emsp 在HotSpot虚拟机中,方法区被称为永久代(Permanent Generation),HotSpot虚拟机的垃圾收集器像管理Java堆一样管理这部分内存,该区域的内存回收行为较少出现,该区域内存回收的主要目标是针对常量池的回收对类型的卸载

运行时常量池

  方法区中有一个部分叫做运行时常量池(Runtime Constant Pool),该区域保存的就是编译器生成的各种字面量、符号引用和直接引用

文章目录
  1. 1. Java运行时数据区域划分
  2. 2. 程序计数器
  3. 3. Java虚拟机栈和本地方法栈
    1. 3.1. Java虚拟机栈
    2. 3.2. 本地方法栈
  4. 4. Java堆
  5. 5. 方法区
    1. 5.1. 运行时常量池