00:00
那我们下边呢,就开始正式的来讲解运行时数据区了,那运行时数据区里边我们首先带大家来讲的叫做程序计数器,哎,我这有个小括号,就是也称作呢叫做PC计存器,当然英文呢就只有一个名是中文呢,我们这两个名字呢都可以,一会呢我们再解释这个问题,那这一章呢,我们一共讲三个知识点,第一个呢,就是关于程序计数器的一个介绍,呃,下边呢是一个举例说明,然后呢有两个常见的问题。好,那我们主要呢,先来看第一个关于PC寄存器它的一个介绍,那说到这个介绍和使用的话呢,那当然首推咱们官网这个Oracle提供的虚拟规范里边关于这个PC寄存器的一个介绍是什么样子的,这下边呢,我附了这个链接地址啊,这个大家呢,直接可以把这个链接地址呢,诶CTRLC好不容易过来诶粘这个粘进去诶就能够打开,我们现在用的呢,是JAVA8的这个虚拟机规范,大家呢,也可以看一下,比较新的像11啊都可以。那么关于我们说这个内存结构这块呢,在八以后其实变化呢不算太大,所以大家呢,其实看八呢也没有问题,哎,在垃圾回收方面呢,会有一些变化啊。
01:21
那这个文档呢,大家可能直接从这个地址就能过来,那如果没有这个地址怎么办呢?咱们也可以呢,通过官网呢,进来再说一下如何进来。这呢是咱们这个Oracle的官网,点一下这个三道杠,找一下这个叫downloads。然后呢,找到我们这个Java。然后呢,选JDK。这呢就是我们JDK的一个下载页面了,接着大家往后找,我们会有专门提到这个文档的位置。那这呢就提到文档了,文档的话呢,比如我们就先选一下这个Java SE的八。那进来以后呢,左边这个列表里边有一个specifications啊,点一下就是关于我们这的规范,那这呢就列举出来了,我们到目前Java se13,诶各个版本的Java语言的规范和Java虚拟机的规范,那如果我们要是看八的话呢,就可以直接找到这儿,呃,点一下atl在这呢,我们就进来了,那进来以后呢,前面是一个目录,那么这个目录呢,往下边找这个2.5呢,就叫做运行时数据区。
02:28
在它下面的第一项就叫做PC寄存器,点开这呢就是关于PC寄存器的介绍啊,非常少是吧,非常的简洁啊,正如我们PC寄存器本身也比较小一样,内容呢也比较少。那咱这就不在这看这个英文了,诶直接呢回过来看这个中文,其中的一些重要信息呢,咱们都已经翻译过来了啊,诶刚才说了,我们这个讲一下运营式数据区,咱们现在讲的是这个PC寄存器啊,或叫程序记录器都行,这个英文的话呢,叫做program counter register,你要是直译的话呢,应该叫程序计数寄存器。
03:06
程序计数寄存器,这样呢,叫起来感觉有点长,所以呢,我们经常称为叫PC寄存器。啊,或者呢,就直接叫做程序计数器啊,程序计数器呢,其实相当于把这个register给忽略掉也啊呃,但是基本上能够表达出来我们这个PC计算器它的一个主要作用啊,所以我们叫做这个程序计数器也OK啊。这个呢,它的这个命名主要呢,是源于咱们CPU里边有一个叫做寄存器,所以说呢,呃,有同学在这个知乎上问哈,我看到过一些问题,就是说这个Java虚拟当中存不存在寄存器结构呢,这个其实呢,可以打是存在的,那理解成呢,就是我们Java虚拟机当中的叫PC寄存器啊,也叫做程序计录器,就可以理解成是CPU当中的这个寄存器的类似的一个结构啊,是一个抽象的模拟啊,是对物理的PC寄存器,或者叫这个寄存器的一个抽象模拟。
04:05
那不是一个东西啊,我们这是一个软件层面的概念啊,是这样子的,那PDA寄存器呢,主要来存储指令相关的这个现场信息,呃,CPU呢,只有把数据装载到呃这个寄存器里边才可以去运行啊这样子的啊啊那大家平时叫它的话呢,你就叫做PC寄存器,或者叫程序计录器,都可以说的呢,都是它啊,那也称作呢,叫程序的钩子。这个钩子怎么来理解呢?这个大家吃过这个北京烤鸭哈,北京烤鸭呢,在烤的时候那个大的炉子嘛,是吧,炉子里边呢,就是一个钩子,一个钩子呢,来勾这个成,呃,勾这个鸭子的哈,那程序钩子呢,你可以理解成这个钩子呢,是专门来勾程序的,程序呢,我们可以理解为就是这个线程当中一行一行执行的代码,那我们这个钩子呢,来勾着一行行的代码,说白了就是我们的,呃,也可以理解成叫做行号指示器。就是我们执行完上一行代码以后,下一行该执行谁了,那由我们这个程序计数器来做一个记录啊,这就是他的一个作用啊。
05:07
好,那我们看一下这个官方怎么来说这个具体的作用,说PCA寄存器是用来存储指令,呃,存储指向下一条指令的地址啊,也就是即将要执行的这个指令代码啊,由执行引擎呢,来去读取下一条指令啊,那这儿呢,我放了一个图,哎,这个图呢,你看是这样子的啊,一会儿咱们也会这个具体说明到这个,呃。我们说呢,叫PD寄存器哈,这个PD寄存器呢,是每一个线程有一份,每一个线程有一份,然后我们这个代码的话,或者叫这个指令哈,我们会给它分配在相应的这个战的空间当中啊,这里边又提到战针,咱们后面来介绍这一个战针呢,其实是对应的一个方法,哎,我们在ae方法中调用二,方法二里边又调用的NN又调用它,哎,就依次呢去压入站,哎最上面的也就算当前方法了哈,然后呢,我们这个里边具体这些指令呢,都有一个啊,叫做这个行号的一个标识,那PD寄存器呢,就相当于是这个行号的标识啊,记录了下一条指令的个地址,那么指引引擎呢,根据这个地址就取下一条指令,那执行完这条指令以后呢,再去PC寄存器里边呢,去取,再下一条的指令啊,再去执行,这就是我们PC寄存器的一个作用,就是来存储下一条指令地址的。
06:27
哎,大家记住这个事儿就行啊啊,那么它呢,是一块很小的内存空间啊,小到呢几乎可以忽略不计,也是运行速度最快的一个内存区域。啊,这个小到可以忽略不计,那确实啊,它只是存储一个,呃,下一条指令的地址嘛,啊就是很小了啊,那运行速度最快,它就直接呢,就是取,取了以后呢,他再记录下一条,呃,运行运行速度是比较快的。那在虚拟当中呢,我们说每个线程都有自己的程序计数器,就记录你自己线程执行到哪儿了啊,说白了就是这个意思啊,呃,是线程私有的生命周期呢,与咱们线程的生命周期保持一致啊,只要是线程私有的呢,都是生命周期一致的。
07:09
刚才呢,我们提到一个概念说,呃,叫做这个最上面执行的这个方法呢,咱们称作呢,叫做当前方法。啊,最上面这个我们称为叫当前方法啊,那么这个程序计数器呢,会存储当前线程正在执行的Java方法,也就是当前方法中的这个GM的一个指令地址。啊,记住这个地址,呃,这个如果呢,我们执行的是native的方法,说这就是未指定的值,诶大家可能会有点迷惑哈,说咱们现在说的这块,你看我这指的是一个,呃,这其实算是虚拟基站了哈,呃,那你这又提到的说这个另外的一个本地方法,这就涉及到一个本地方法站。啊,涉及到一个本地方法站,那你要是一个本地方法站的话呢,我们记录这个地址就是未指定的值的,因为我们这是一个Java层面的一个呃,寄存器哈,然后呢,你调用这个C的时候呢,我们就显示不出来了啊,所以就安底少了一个I啊叫UN DeFine。
08:09
好,这是这个,然后呢说它是程序,哎,控制流的一个指示器啊,分支循环跳转,异常线程恢复啊都需要用过,通过它呢来做一个指示,诶也很好理解哈,诶刚才我们说的它就相当于是一个行号指示器,其实呢,也可以理解成这个,大家应该是,嗯,比如说数据库当中,数据库当中我们这个要取数据库中一个一个这个表中的一行数据的话呢,咱们这个有一个叫结果集是吧,结果级一行一行去取这个数据。啊,或者呢,我们至少有过这个叫游标的一个概念是吧,它就好比是我们这个游标一样。啊,那大家学习这个,学习过这个Java中的这个集合是吧,那集合中呢,我们有很多的数据,你可以理解成呢,我们便利集合中数据的话呢,这叫迭代器啊,只是呢,我现在到哪了啊,一行一行调这个next去执行。
09:00
啊,所以说呢,我们这个PC寄存器呢,大家就可以理解成是咱们的油标或者是呃,集合的这个迭代器一样,那就可以了啊。嗯,下边的话呢,你看他提到一个说它是唯一个在Java虚拟当中规范里边没有这个auto memory error的一个区域啊,这个呢,还是确实很特别的哈,那这块我们想说这样一个事情,呃,结合我们后边呢,要说的几个运营师数据区的这个结构哈,我们关注的首先是JC啊,然后呢,我们写一个叫哎OM啊这呢我想说明什么问题呢。是这样子的啊,就是我们后边呢会关注,诶我们后边呢会关注说呢具体的一个区域呢,它有没有JC。啊,有没有垃圾回收机制,比如说咱们的这个站结构啊,站呢是也不考虑垃圾回收了,它只有这个入站出站这个操作,它没有垃圾回收,而我们这个堆和方法区呢,是有垃圾回收的。啊,这俩有垃圾回收,这没有垃圾回收,而我们这个PC寄存器呢,也没有垃圾回收,它就只是下一个地址的啊,不断的被替换成下一个地址,所以他也没有垃圾回收啊,这是明确这个概念啊,然后呢,我们又提到一个叫做oom,就是是不是会报异常呢?啊,内存溢出的异常呢,那还回过去PC寄存器oom也不会发生。
10:23
它不会发生,而我们这个站,不管你是虚拟基站还是本地方法站,是站结构呢,它没有垃圾回收,但是有可能会溢出。有可能会溢出啊,因为马上就溢出了嘛,对吧,那我们hi跟这个method呢,它也可能会溢出。啊,也可能会溢出,所以说呢,我们整个这几个结构呢,只有我们这个PC寄存器比较特别,它既没有JC也没有oom啊这个大家注意一下啊行,那我们对于这个PC寄存器到底是什么啊,什么作用,大家呢,先整体上有一个概念啊就可以了。
我来说两句