一、PC寄存器概述
CPU只有把數據裝載到寄存器才能夠運行。這里,并非是廣義上所指的物理寄存器,或許將其翻譯為PC計數器(或指令計數器)會更加貼切(也稱為程序鉤子),并且也不容易引起一些不必要的誤會。JVM中的PC寄存器是對物理PC寄存器的一種抽象模擬。
簡單介紹
1、 PC寄存器是一塊很小的內存空間,幾乎可以忽略不計,也是運行速度最快的存儲區域。
2、 在JVM規范中,每個線程都有它自己的PC寄存器,是線程私有的,生命周期與線程的生命周期保持一致。
3、 任何時間一個線程都只有一個方法在執行,也就是所謂的當前方法,PC寄存器會存儲當前線程的正在執行的Java方法的JVM指令地址;或者,如果是執行的native方法,則是未指定值。
4、 PC寄存器是程序控制流的指示器,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個寄存器來完成。
5、 字節碼解釋器工作時就是通過改變這個寄存器的值來選取下一條需要執行的字節碼指令。
6、 PC寄存器是唯一 一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。
注:方法區(元數據區)和堆區是有GC(垃圾回收)的,而棧區和PC寄存器是沒有的;棧區、方法區、堆區是有OOM(OutOfMemoryError)的,而PC寄存器沒有。
二、PC寄存器的作用
PC寄存器用來存儲指向下一條指令的地址,即將要執行的指令代碼。由執行引擎讀取下一條指令。
每一個棧幀就相當于存儲了一個方法,棧幀中的每一個指令都有一個標識,這里PC寄存器就存儲了指令的地址,起標識作用,然后執行引擎就根據這個標識來讀取到下一條指令。
三、PC寄存器舉例說明
public class PcRegisterTest { public static void main(String[] args) { int i = 10; int j = 5; int k = i+j; } }
這里我們運行編譯下這段代碼,然后在進入到out對應的目錄下執行javap命令:
我們就可以看到反編譯的一個結果:
上圖紅色框里的數字就是指令地址或者偏移地址,其就是PC寄存器里面存儲的地址。藍色框里的就是操作指令。然后執行引擎就根據這個指令地址取出指定的操作指令來操作虛擬機棧(局部變量表、操作數表),并且翻譯成機器指令,讓CPU對相應的計算。
四、解決PC寄存器常問到的兩個面試問題
1、使用PC寄存器存儲字節碼指令地址有什么用呢?
(為什么使用PC寄存器記錄當前線程的執行地址呢?)
因為CPU需要不停的切換各個線程,這時候切換回來后,就得知道是從哪個指令開始繼續執行。JVM的字節碼解釋器就需要通過改變PC寄存器的值來明確下一條應該執行什么樣的字節碼按指令。
2、PC寄存器為什么會被設定為線程私有的,一個線程一份?
我們都知道所謂的多線程在一個特定的時間段內只會執行其中某一個線程的方法,CPU會不停地做任務切換,這樣必然導致經常中斷或恢復,如何保證分毫無差呢?
1.為了能夠準確地記錄各個線程正在執行的當前字節碼指令地址,最好的辦法自然是為每一個線程都分配一個PC寄存器,這樣一來各個線程之間便可以進行獨立計算,從而不會出現相互干擾的情況。
2.由于CPU時間片輪限制,眾多線程在并發執行過程中,任何一個確定的時刻,一個處理器或者多核處理器中的一個內核,只會執行某個線程中的一條指令。
3.這樣必然導致經常中斷或恢復,如何保證分毫無差呢?每個線程在創建后,都會產生自己的程序計數器和棧幀,程序計數器在各個線程之間互不影響。
五、CPU時間片
CPU時間片: 即CPU分配給各個程序的時間,每個線程被分配一個時間段,稱作它的時間片。
在宏觀上: 我們可以同時打開多個應用程序,每個程序并行不悖,同時運行。
但在微觀上: 由于只有一個CPU,一次只能處理程序要求的一部分,如何處理公平,一種方法就是引入時間片,每個程序輪流執行。
總的來說,我們用一句話來概括:宏觀并行,微觀并發。
簡單圖示:
PC寄存器就到這里以上就是JVM中的程序計數寄存器PC原理分析的詳細內容,更多關于JVM程序計數寄存器PC原理的資料請關注服務器之家其它相關文章!
原文鏈接:https://blog.csdn.net/weixin_45827693/article/details/117283089