1. 程式人生 > 實用技巧 >程式計數器

程式計數器

https://docs.oracle.com/javase/specs/jvms/se8/html/

介紹

JVM中的程式計數暫存器(Program Counter Register)中,Register的命名源於CPU的暫存器,暫存器儲存指令相關的現場資訊CPU只有把資料裝載到暫存器才能夠執行。

這裡,並非是廣義上所指的物理暫存器,或許將其翻譯為PC計數器(或指令計數器)會更加貼切(也稱為程式鉤子),並且也不容易引起一些不必要的誤會。JVM中的PC暫存器是對物理PC暫存器的一種抽象模擬。

它是一塊很小的記憶體空間,幾乎可以忽略不記。也是執行速度最快的儲存區域。

在JVM規範中,每個執行緒都有它自己的程式計數器,是執行緒私有的

,生命週期與執行緒的生命週期保持一致。

任何時間一個執行緒都只有一個方法在執行,也就是所謂的當前方法。程式計數器會儲存當前執行緒正在執行的Java方法的JVM指令地址;或者,如果是在執行native方法(本地方法,java中由c++編寫的核心方法),則是未指定值(undefined)

它是程式控制流的指示器,分支、迴圈、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴這個計數器來完成。位元組碼直譯器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令。

它是唯一一個在Java虛擬機器規範中沒有規定任何 OutOfMemoryError 情況的區域。

作用

PC暫存器用來儲存指向下一條指令的地址

,也即將要執行的指令程式碼。由執行引擎讀取下一條指令

舉例說明

package com.atguigu.java;

public class PCRegisterTest {
    public static void main(String[] args) {
        int i = 10;
        int j = 20;
        int k = i + j;
    }
}

然後將程式碼進行編譯成位元組碼檔案,我們再次檢視 ,發現在位元組碼的左邊有一個行號標識,它其實就是指令地址,用於指向當前執行到哪裡。

Code:
	stack=2, locals=4, args_size=1
        0: bipush        10
        2: istore_1
        3: bipush        20
        5: istore_2
        6: iload_1
        7: iload_2
        8: iadd
        9: istore_3
        10: return
package com.atguigu.java;

public class PCRegisterTest {
    public static void main(String[] args) {
        int i = 10;
        int j = 20;
        int k = i + j;

        String s = "abc";
        System.out.println(i);
        System.out.println(k);
    }
}

三個常見問題

使用PC暫存器儲存位元組碼指令地址有什麼用呢?為什麼使用PC暫存器記錄當前執行緒的執行地址呢?

因為CPU需要不停的切換各個執行緒,這時候切換回來以後,就得知道接著從哪開始繼續執行。

JVM的位元組碼直譯器就需要通過改變PC暫存器的值來明確下一條應該執行什麼樣的位元組碼指令。

PC暫存器為什麼被設定為私有的?

我們都知道所謂的多執行緒在一個特定的時間段內只會執行其中某一個執行緒的方法,CPU會不停地做任務切換,這樣必然導致經常中斷或恢復,如何保證分毫無差呢?為了能夠準確地記錄各個執行緒正在執行的當前位元組碼指令地址,最好的辦法自然是為每一個執行緒都分配一個PC暫存器(因此我們說PC計數器是執行緒私有的),這樣一來各個執行緒之間便可以進行獨立計算,從而不會出現相互干擾的情況。

由於CPU時間片輪限制,眾多執行緒在併發執行過程中,任何一個確定的時刻,一個處理器或者多核處理器中的一個核心,只會執行某個執行緒中的一條指令。

這樣必然導致經常中斷或恢復,如何保證分毫無差呢?每個執行緒在建立後,都會產生自己的程式計數器和棧幀,程式計數器在各個執行緒之間互不影響。

儲存現場

CPU時間片

CPU時間片即CPU分配給各個程式的時間,每個執行緒被分配一個時間段,稱作它的時間片。

在巨集觀上:我們可以同時開啟多個應用程式,每個程式並行不悖,同時執行。

但在微觀上:由於只有一個CPU,一次只能處理程式要求的一部分,如何處理公平,一種方法就是引入時間片,每個程式輪流執行。