java虚拟机-程序计数器PC Register
什么是程序計(jì)數(shù)器?
程序計(jì)數(shù)器是一塊 較小 的內(nèi)存空間,它可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的 行號(hào)指示器 ;在虛擬機(jī)的概念模型里(僅僅是概念模型,各種虛擬機(jī)可能會(huì)通過一些更高效的方式去實(shí)現(xiàn)),字節(jié)碼解釋器工作時(shí),就是通過改變這個(gè)計(jì)數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳準(zhǔn)、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)數(shù)器來完成 ;
簡單的理解為,是程序計(jì)數(shù)器保證了程序的正常執(zhí)行 ;
?
有什么特點(diǎn)
- 線程私有的
 - 是java虛擬機(jī)規(guī)范里面, 唯一 一個(gè) 沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域
 - 生命周期隨著線程,線程啟動(dòng)而產(chǎn)生,線程結(jié)束而消亡
 
?
為什么具有這些特點(diǎn)
這里重點(diǎn)理解 :程序計(jì)數(shù)器,可以看做是當(dāng)前線程執(zhí)行的字節(jié)碼的 行號(hào)指示器 ,這句話;要理解這句話,需要先知道字節(jié)碼文件長什么樣子,看下面的代碼
// java 文件被翻譯為字節(jié)碼的時(shí)候,字節(jié)碼大概類似于下面的樣子 public void haha(){ // 原來的 haha 方法內(nèi)部的 java 代碼,被翻譯為下面的類似于匯編語言的指令 0 xxxx .... 2 xxxx .... 4 xx ... 5 xxx ... }?上面左邊的 0、2、4、5 ,就是類似于字節(jié)碼的行號(hào)(實(shí)際是指令的偏移地址),程序計(jì)數(shù)器中保存中的值,就是它們;字節(jié)碼解釋器,就是根據(jù)它們,來執(zhí)行程序的 ;
理解了程序計(jì)數(shù)器,就好理解它的這些特點(diǎn)了;
我們都知道,java是支持多線程的,當(dāng)CPU執(zhí)行權(quán)從 A 線程,轉(zhuǎn)移到 B 線程的時(shí)候,JVM就要暫時(shí)掛起線程 A ,去執(zhí)行線程 B ;當(dāng)線程 A 再次得到CPU執(zhí)行權(quán)的時(shí)候,又會(huì)掛起B(yǎng)線程,繼續(xù)執(zhí)行 A 線程 ;
我們想象下,CPU是怎么知道記住之前A線程,執(zhí)行到哪一處的?
答案是,CPU根本就不會(huì)記住之前執(zhí)行到哪里了,它只是埋頭苦干;那是什么保證了切換線程的程序可以正常執(zhí)行的;答案是 : 程序計(jì)數(shù)器 ;程序計(jì)數(shù)器里面保存的是 當(dāng)前線程執(zhí)行的字節(jié)碼的行號(hào)(看著像行號(hào),其實(shí)是指令地址);
那么,我們需要幾個(gè)程序計(jì)數(shù)器呢?如果,我們只有一個(gè)的話,切換B線程以后,程序計(jì)數(shù)器里面保存的就是B線程所執(zhí)行的字節(jié)碼的行號(hào)了,再切換回A線程,就蒙圈了,不知道執(zhí)行到哪里了,因?yàn)?#xff0c;程序計(jì)數(shù)器里面保存的是B線程當(dāng)前執(zhí)行的字節(jié)碼地址 ;因此,我們可以想象出,要為每個(gè)線程都分配一個(gè)程序計(jì)數(shù)器,因此,程序計(jì)數(shù)器的內(nèi)存空間是線程私有的 ;這樣即使線程 A 被掛起,但是線程 A 里面的程序計(jì)數(shù)器,記住了A線程當(dāng)前執(zhí)行到的字節(jié)碼的指令地址了 ,等再次切回到A線程的時(shí)候,看一下程序計(jì)數(shù)器,就知道之前執(zhí)行到哪里了!
?
那么程序計(jì)數(shù)器,什么時(shí)候分配內(nèi)存呢?我們?cè)囅胂?#xff0c;一個(gè)線程在執(zhí)行的任何期間,都會(huì)失去CPU執(zhí)行權(quán),因此,我們要從一個(gè)線程被創(chuàng)建開始執(zhí)行,就要無時(shí)無刻的記錄著該線程當(dāng)前執(zhí)行到哪里了!因此,線程計(jì)數(shù)器,必須是線程被創(chuàng)建開始執(zhí)行的時(shí)候,就要一同被創(chuàng)建;?
程序計(jì)數(shù)器,保存的是當(dāng)前執(zhí)行的字節(jié)碼的偏移地址(也就是之前說的行號(hào),其實(shí)那不是行號(hào),是指令的偏移地址,只是為了好理解,才說是行號(hào)的,),當(dāng)執(zhí)行到下一條指令的時(shí)候,改變的只是程序計(jì)數(shù)器中保存的地址,并不需要申請(qǐng)新的內(nèi)存來保存新的指令地址;因此,永遠(yuǎn)都不可能內(nèi)存溢出的;因此,jvm虛擬機(jī)規(guī)范,也就沒有規(guī)定,也是唯一一個(gè)沒有規(guī)定 OutOfMemoryError 異常 的區(qū)域; ;
?
當(dāng)線程執(zhí)行的是本地方法的時(shí)候,程序計(jì)數(shù)器中保存的值是空(undefined);原因很簡單:本地方法是C++/C 寫的,由系統(tǒng)調(diào)用,根本不會(huì)產(chǎn)生字節(jié)碼文件,因此,程序計(jì)數(shù)器也就不會(huì)做任何記錄 ;
?
轉(zhuǎn)自:https://blog.csdn.net/youngyouth/article/details/79868299
轉(zhuǎn)載于:https://www.cnblogs.com/qjm201000/p/10481946.html
總結(jié)
以上是生活随笔為你收集整理的java虚拟机-程序计数器PC Register的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 怀念过去的简短句子187个
 - 下一篇: Git同时使用不同平台代码仓库