(轉(zhuǎn)載)JVM 程序計數(shù)器
2018-01-02 17:13:10?獼猴桃0303?
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/leaf_0303/article/details/78953669
程序計數(shù)器是一塊較小的內(nèi)存空間,它的作用可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。在虛擬機(jī)的概念模型里字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個計數(shù)器來完成。- - 摘自《深入理解Java虛擬機(jī)》
特 點(diǎn)
如果線程正在執(zhí)行的是Java 方法,則這個計數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令地址
如果正在執(zhí)行的是Native 方法,則這個技術(shù)器值為空(Undefined)
此內(nèi)存區(qū)域是唯一一個在Java虛擬機(jī)規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域
一、程序計數(shù)器會隨著線程的啟動而創(chuàng)建,先來直觀的看下計數(shù)器中會存哪些內(nèi)容
有代碼如下
package com.xnccs.cn.share;
public class ShareCal {
? ? public int calc(){
? ? ? ? int a = 100;
? ? ? ? int b = 200;
? ? ? ? int c = 300;
? ? ? ? return ( a + b ) * c;
? ? }
}
————————————————
這是一段非常簡單的計算代碼,我們先編譯成Class 文件再使用 javap 反匯編工具看下class 文件中數(shù)據(jù)格式,如下圖

圖中使用紅框框起來的就是字節(jié)碼指令的偏移地址,偏移地址對應(yīng)的bipush?等等是jvm 中的操作指令,這是入棧指令。這里不作詳細(xì)分析,有機(jī)會再分享。 當(dāng)執(zhí)行到方法calc()時在當(dāng)前的線程中會創(chuàng)建相應(yīng)的程序計數(shù)器,在計數(shù)器中為存放執(zhí)行地址 (紅框中的)0 2 3…等等

這也說明在我們程序運(yùn)行過程中計數(shù)器中改變的只是值,而不會隨著程序的運(yùn)行需要更大的空間,也就不會發(fā)生溢出情況。–特點(diǎn)3
二、舉例理解程序計數(shù)器
說線程恢復(fù)等基礎(chǔ)功能都需要依賴這個程序計數(shù)器來完成,首先我們得知道:
線程是CPU 最小的調(diào)度單元
Java 虛擬機(jī)的多線程是通過切換線程并分配處理器執(zhí)行時間的方式來實(shí)現(xiàn)的,在任何一個確定的時間,一個處理器(對于多核處理器來說是一個內(nèi)核)都只會執(zhí)行一條線程中的指令
如有如下圖過程,當(dāng)A 線程先向處理器發(fā)出指令,但當(dāng)執(zhí)行到中途一半時,B線程過來執(zhí)行,且優(yōu)先級高,此時處理器將A 掛起,B 執(zhí)行,當(dāng)B 執(zhí)行結(jié)束需要喚醒A 同時得知道A 的執(zhí)行位置,就可以查看線程A 中的計數(shù)器指令

三、為什么執(zhí)行的是native 方法時,為undefined
由上我們知道計數(shù)器記錄的字節(jié)碼指令地址,但是native 本地(如:System.currentTimeMillis()/ public static native long currentTimeMillis();)方法是大多是通過C實(shí)現(xiàn)并未編譯成需要執(zhí)行的字節(jié)碼指令所以在計數(shù)器中當(dāng)然是空(undefined).
問: 那native 方法的多線程是如何實(shí)現(xiàn)的呢?
答:?native 方法是通過調(diào)用系統(tǒng)指令來實(shí)現(xiàn)的,那系統(tǒng)是如何實(shí)現(xiàn)多線程的則 native 就是如何實(shí)現(xiàn)的
摘博客一段話:
Java線程總是需要以某種形式映射到OS線程上。映射模型可以是1:1(原生線程模型)、n:1(綠色線程 / 用戶態(tài)線程模型)、m:n(混合模型)。以HotSpot VM的實(shí)現(xiàn)為例,它目前在大多數(shù)平臺上都使用1:1模型,也就是每個Java線程都直接映射到一個OS線程上執(zhí)行。此時,native方法就由原生平臺直接執(zhí)行,并不需要理會抽象的JVM層面上的“pc寄存器”概念——原生的CPU上真正的PC寄存器是怎樣就是怎樣。就像一個用C或C++寫的多線程程序,它在線程切換的時候是怎樣的,Java的native方法也就是怎樣的。
作者:RednaxelaFX鏈接:https://www.zhihu.com/question/40598119/answer/87381512