Skip to content

程序计数器

程序计数器是线程私有的小块内存,用来记录当前线程正在执行的字节码指令位置。它很少直接导致线上故障,但对理解线程切换、字节码执行和异常栈很重要。

作用

Java 线程执行字节码时,程序计数器保存当前指令位置。线程被 CPU 切走再切回来时,JVM 需要知道从哪里继续执行。

text
线程 A -> 执行到指令 15 -> 被切走
线程 B -> 执行
线程 A -> 恢复到指令 15 继续执行

特点

项目说明
线程关系每个线程独立拥有
生命周期随线程创建和销毁
存储内容当前字节码指令地址或执行位置
常见异常规范中没有规定该区域 OOM
对 native 方法执行 native 方法时值可能为空或未定义

和栈的关系

程序计数器记录“执行到哪里”,虚拟机栈记录“方法调用现场”。两者配合让线程可以暂停、恢复和继续执行。

区域关注点
程序计数器当前执行指令位置
虚拟机栈当前调用链和每个方法的栈帧

为什么需要了解它

理解多线程

多线程不是每个线程一直占着 CPU。线程会频繁切换,程序计数器帮助 JVM 恢复每个线程自己的执行位置。

理解字节码

查看字节码:

bash
javap -c Demo

输出中的偏移量可以理解为指令位置。程序计数器保存的就是类似位置。

理解异常栈

异常栈展示方法调用链,程序计数器和栈帧共同帮助 JVM 定位执行现场。

排查价值

程序计数器很少是问题根因,但它能帮助理解:

  • 为什么线程切换后还能继续执行。
  • 为什么每个线程有独立调用栈。
  • 字节码跳转、循环、异常处理如何定位。

遇到实际问题时,通常看的是线程栈:

bash
jstack <pid>
jcmd <pid> Thread.print

程序计数器作为底层概念理解即可,不需要单独调参。

别急,先让缓存热一下。