一、概述

  1. 内存
  • 内存是非常重要的系统资源,是硬盘和CPU的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。
  • JVM内存布局规定了Java程序在运行过程中内存申请分配管理的策略,保证了JVM的高效、稳定运行。
  • 不同JVM对内存划分方式和管理机制存在差异。比如JRockit和J9虚拟机无Method Area(方法区)。
  1. HotSpot JVM 运行时数据区

HotSpot_JVM_运行时数据区.png

HotSpot_JVM_运行时数据区_2.png

  1. 方法区(Method Area)堆(Heap)线程共享
  • 方法区 => 元数据 + JIT编译产物
  • 堆 => 主要是对象

关于线程共享的说明 => 每一个JVM只有一个java.lang.Runtime(运行时)对象

  1. 虚拟机栈(Java Stack)程序计数寄存器(Program Counter Register)本地方法栈(Native Method Stack)线程独享。
  • 生命周期与线程一致,随线程创建而创建,随线程销毁而消亡。

二、程序寄存计数器(Program Counter Register)

1. 概述

  1. Register命名来源于CPU的寄存器,存储指令相关的现场信息,CPU只有把数据装载到寄存器才能运行。
  2. JVM中的Program Counter Register是对物理PC寄存器的一种抽象的模拟,或许翻译为PC计数器更贴切。
  3. 是一块很小的,在内存中运行速度最快的内存空间,几乎可以忽略不记。
  4. 每一个线程有一个PC程序计数器(线程私有),生命周期与线程一致。
  5. 任何时间一个线程都只有一个方法在执行,即所谓的当前方法
    • 程序计数器会存储当前线程正在执行的方法的JVM指令地址
    • 如果执行的是native方法,则是未指定值(undefined)
  6. 它是程序控制流指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖PC程序计数器完成。
  7. 字节码解释器工作时,就是通过改变计数器值选取下一条需要执行的字节码指令。
  8. JVM规范中唯一一个没有OutOfMemoryError的区域。 | 内存区域 | 是否有GC(垃圾回收) | 是否有OOM(内存溢出) | | —- | —- | —- | | Java Stack(虚拟机栈) | 否 | 是 | | Heap(堆) | 是 | 是 | | Method Area(方法区) | 是 | 是 | | PC寄存器 | 否 | 否 |

2. 工作流程

1) 作用描述

PC寄存器作用描述.png

2) 工作原理示例

PC寄存器工作示例.png

3) 面试中两个常见问题

  1. 使用PC寄存器存储字节码指令地址有什么用?为什么使用PC寄存器记录当前线程的执行地址呢?

执行引擎切换线程.png

  • CPU需要不停切换线程,当切换回来的时候,就得知道接着从哪个指令开始执行。
  • JVM的字节码解释器就是通过改变PC寄存器所存的字节码指令地址的值来明确下一条该执行的指令。
    1. 为什么PC寄存器为什么被设定为每个线程独有一份
  • 记录每个线程正在执行的当前字节码指令地址,最好的办法是每个线程一份。这样各个线程直接可以进行独立计算不会互相干扰