WHCSRL 技术网

JVM系列---内存结构(运行时数据区)

一、内存结构(运行时数据区)

这里引用尚硅谷的中英文的图(运行时数据区
运行时数据区
中文

二、程序计数器(PC寄存器)

概念:

JVM中的程序计数寄存器( Program Counter Register) 中,Register 的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。 CPU只有把数据装载到寄存器才能够运行。

理解:

  • 运行时数据区的后三者(虚拟机栈、PC寄存器、本地方法栈)是线程私有的==>即用来操作当前线程、记录当前线程的(避免与其他线程冲突)
  • 而PC寄存器则主要是记录当前线程运行的指令到了多少条(毕竟是用来计数【记录着指令数量】嘛,挺好理解的)了---->多线程切换时需要的重点(即切换回当前线程时,还得记得它之前运行到哪条指令了)

作用:

PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一.条指令。

三、虚拟机栈

概念:

  • 内存中的栈和堆:栈是运行时的单位,堆是存储时的单位
  • 生命周期:与线程一致
  • 优缺点:优点是跨平台,指令集小(八位),编译器容易实现(进栈出栈),缺点是性能下降,实现同样的功能需要更多的指令。
  • 对于栈不存在垃圾回收问题(存在OOM栈溢出、不存在GC)
  • 管理Java方法的调用

作用:

  • 主管Java程序的运行,它保存方法的局部变量(8种基本数据类型、 对象的引用地址)、部分结果,并参与方法的调用和返回。

栈的存储单位:

看图,可以发现它是由许多单位的组成的(这个单位就是栈帧),
而这每个栈帧又由(LV【局部变量表】、OS【操作数栈-】、DL【动态链接】、RS【方法返回地址】、以及一些附加信息)组成

当前线程:
在这里插入图片描述

  • 局部变量表(本地变量表Local variable)
    栈帧中,与性能调优最为密切的部分:在方法运行时,虚拟机使用局部变量表完成方法的传递
    局部变量表的变量也是重要的垃圾回收根节点:只要被局部变量表中直接或间接引用的对象都不会回收

  • 操作数栈(表达式栈)
    作用:主要用于保存计算过程中的中间结果,同时作为计算过程中变量临时的存储空间
    虽然是栈,它却是用数组这个结构来实现的(依然只是栈的操作:入栈、出栈)

  • 动态链接(指向运行时常量池的方法引用)
    每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。
    包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接
    (Dynamic Linking) 。比如: invokedynamic指令

  • 方法返回地址(方法正常退出或异常退出的定义)
    作用:存放调用该方法的pc寄存器的值(pc寄存器存储方法下一条指令的值)

四、本地方法栈

概念:

  • 区别于虚拟机栈(管理Java方法的调用),本地方法栈(管理非Java的方法【C语言实现的方法】的调用【native】)
  • 线程私有
  • 它的具体做法是Native Method Stack中 登记native方法,在
    Execution Engine 执行时加载本地方法库。
    在这里插入图片描述

java代码中,只能看到native标明的方法,但是没有具体实现(因为是C实现的),直接使去本地方法库找了。

  • 当某个线程调用-一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。它和虛拟机拥有同样的权限。
    1、本地方法’可以通过本地方法接口来访问虚拟机内部的运行时数据区。
    2、它甚至可以直接使用本地处理器中的寄存器。
    3、直接从本地内存的堆中分配任意数量的内存。

五、堆

概念:

  • 所有的对象实例以及数组都应当在运行时分配在堆上
  • 数组和对象可能永远不会保存在栈上,因为栈帧保存引用(这个引用 指向堆中的对象或数组的位置)
  • 堆中的对象不会伴随方法结束被移除,而是在垃圾收集时才会被移除
  • GC执行重点区域

堆空间内部结构(Java8):

  • 新生区(生命周期较短的瞬时对象(创建与消亡速度非常迅速))
    Eden、Survivor0、Survivor1(8:1:1)
  • 养老区
    Tenured
  • 元空间
    方法区

GC收集分两种:

  • 部分收集(Partial GC)
    ------不是完整收集整个Java堆的垃圾收集
    1、新生代收集(Minor GC/ Young GC )
    2、老年代收集(Major GC/ Old GC)
    3、混合收集(Mixed GC)
    收集整个新生代和部分老年代
  • 整堆收集(Full GC)
    -----收集整个Java堆和方法区

六、方法区

概念:

  • 方法区在哪里?
    逻辑上是属于堆的一部分,别名(非堆),目的就是与堆分开,方法区看作是一块独立于Java堆的内存空间
  • 方法区(永久代/元空间)

我们平时代码创建类时的具体
在这里插入图片描述

  • 栈、堆、方法区的交互
    可以清晰看出上面创建类的过程、引用
    在这里插入图片描述
  • 字节码文件加载到方法区的信息
    在这里插入图片描述
  • JDK8的方法区与堆内部
    在这里插入图片描述

静态变量、StringTable原先是在永久代(元空间)中,后来1.8发生了改变—》因为StringTable,创建String太多,所以放到堆中方便清理

  • 方法区的概览
    在这里插入图片描述
推荐阅读