JVM內存模型:程序計數器

1、JVM模型概述

  java虛擬機(JVM)在java程序運行的過程當中,會將它所管理的內存劃分爲若干個不一樣的數據區域,這些區域有的隨着JVM的啓動而建立,有的隨着用戶線程的啓動和結束而創建和銷燬。一個基本的JVM運行時內存模型以下所示:

  上圖展現的是「JAVA SE7」的JVM虛擬機規範。注意,虛擬機規範並非一成不變的,Oracle在發佈新的JAVA版本時,可能會對JVM作必定的優化和改進,例如在JDK8的版本中,方法區被移除,取而代之的是metaspace(元數據空間)。java

  在本章及下面的章節中,將以JDK7的標準做爲例子,對JVM的運行時數據區進行講解。

2、程序計數器(Program Counter Register)

2.1)什麼是程序計數器

  程序計數器是一個記錄着當前線程所執行的字節碼的行號指示器。
  JAVA代碼編譯後的字節碼在未通過JIT(實時編譯器)編譯前,其執行方式是經過「字節碼解釋器」進行解釋執行。簡單的工做原理爲解釋器讀取裝載入內存的字節碼,按照順序讀取字節碼指令。讀取一個指令後,將該指令「翻譯」成固定的操做,並根據這些操做進行分支、循環、跳轉等流程。
  從上面的描述中,可能會產生程序計數器是不是多餘的疑問。由於沿着指令的順序執行下去,即便是分支跳轉這樣的流程,跳轉到指定的指令處按順序繼續執行是徹底可以保證程序的執行順序的。假設程序永遠只有一個線程,這個疑問沒有任何問題,也就是說並不須要程序計數器。但實際上程序是經過多個線程協同合做執行的。
  首先咱們要搞清楚JVM的多線程實現方式。JVM的多線程是經過CPU時間片輪轉(即線程輪流切換並分配處理器執行時間)算法來實現的。也就是說,某個線程在執行過程當中可能會由於時間片耗盡而被掛起,而另外一個線程獲取到時間片開始執行。 當被掛起的線程從新獲取到時間片的時候,它要想從被掛起的地方繼續執行,就必須知道它上次執行到哪一個位置,在JVM中,經過程序計數器來記錄某個線程的字節碼執行位置。所以,程序計數器是具有線程隔離的特性,也就是說,每一個線程工做時都有屬於本身的獨立計數器。

2.2)程序計數器的特色

  1.線程隔離性,每一個線程工做時都有屬於本身的獨立計數器。
  2.執行java方法時,程序計數器是有值的,且記錄的是正在執行的字節碼指令的地址(參考上一小節的描述)。
  3.執行native本地方法時,程序計數器的值爲空(Undefined)。由於native方法是java經過JNI直接調用本地C/C++庫,能夠近似的認爲native方法至關於C/C++暴露給java的一個接口,java經過調用這個接口從而調用到C/C++方法。因爲該方法是經過C/C++而不是java進行實現。那麼天然沒法產生相應的字節碼,而且C/C++執行時的內存分配是由本身語言決定的,而不是由JVM決定的。
  4.程序計數器佔用內存很小,在進行JVM內存計算時,能夠忽略不計。
  5.程序計數器,是惟一一個在java虛擬機規範中沒有規定任何OutOfMemoryError的區域。
相關文章
相關標籤/搜索