程序计数器

一 程序计数器概念
程序计数器是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现)1.字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、2.线程恢复等基础功能都需要依赖这个计数器来完成。- - 摘自《深入理解Java虚拟机》

程序计数器是一块较小的内存空间,可以把它看做当前线程正在执行的字节码的行号指示器.也就是说,程序计数器里面记录的是当前线程正在执行的那一条字节码执行的地址.如果当前线程正在执行的是一个本地方法,那么此时程序计数器为空.(本地方法是保存在动态链接库中)

由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存

如果线程正在执行一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器为空(undefined)。此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

通俗解释

对于一个运行中的java程序而言,其中的每一个线程都有他自己的PC(程序计数器)寄存器,他是在该线程启动时创建的,PC寄存器的大小是一个字长,因此它既能够持有一个本地指针,也能持有一个returnAddress(returnAddress类型会被java虚拟机的jsr、ret和jsr_w指令所使用。returnAddress类型的值指向一条虚拟机指令的操作码。与前面介绍的那些数值类的原生类型不同,returnAddress类型在java语言之中并不存在相应的类型,也无法在程序运行期间更改returnAddress类型的值)。当线程执行某个java方法时 ,PC寄存器的内容总是下一条被执行指令的”地址”,这里的”地址”可以是一个本地指针,也可以是在方法字节码中相对于该方法起始指令的偏移量。如果该线程正在执行一个本地方法,那么PC寄存器的值是”Undefined”。

本地方法和java方法

java中有两种方法:java方法和本地方法。java方法是有java语言编写,编译成字节码,存储在class文件中的。

本地方法是有其它语言(比如C,C++,或者是汇编语言)编写的,编译成和处理器相关的机器代码。本地方法保存在动态连接库中,格式是各个平台专用的。

java方法是与平台无关的,但是在本地方法却不是。

运行中的java程序调用本地方法时,虚拟机装载包含这个本地方法的动态库,并调用这个方法。

二 程序计数器作用
程序计数器的作用有以下两点:

字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,比如:顺序执行/选择/循环/异常处理.
在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪里.
针对第二个作用可以做如下理解:

由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。

如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。(native方法是本地方法)

三 程序计数器特点
1 线程私有的,每个线程都有一个程序计数器. 
2 是java虚拟机规范里面, 唯一 一个 没有规定任何 OutOfMemoryError 情况的区域 
3 生活周期随着线程的创建而创建,随着线程的结束而消亡. 
4 程序计数器是一块较小的内存区域
程序计数器