1. 程式人生 > >java虛擬機器學習之執行緒共享記憶體區和執行緒私有區

java虛擬機器學習之執行緒共享記憶體區和執行緒私有區

 執行緒共享指的就是可以允許被所有執行緒共享訪問的一塊記憶體,包括堆區,方法區和執行時常量池。

 1. java堆區

     java堆區在虛擬機器啟動時被建立,並且他在實際記憶體中是可以不連續的。java堆區是用於儲存物件例項的一塊記憶體,同時也是垃圾回收器執行的重點區域,因為堆區是垃圾回收器的重點回收區域,所以gc極有可能會在大記憶體的使用和回收工作上稱為效能瓶頸。為了解決這個問題,JVM考慮是否一定會將物件的例項儲存到java堆區內。

  基於OpenJDK,深度定製的TaoBaoVM,其中創新的GCIH技術實現將生命週期較長的物件從堆區移動到堆外,並且垃圾回收器不可以處理這塊記憶體,以此降低垃圾回收器的回收頻率和提升垃圾回收器的目的。在某些特殊的應用中有許多很大的物件而且生命週期也很長,那麼他們的存在必定會給垃圾回收器造成很多不必要的工作負擔。假設淘寶有許多大量的重複物件,據說物件超多數百MB。他們本身在應用提供服務前建立,在服務過程中永遠存在,那麼實際垃圾回收器對這塊記憶體做的收集就沒用,如果我們將這些物件移動到堆外那麼他們之前佔據的堆就會不用那麼每次FULLGC時間就會減少,GCIH

為在jvm間共享物件提供了必要的基礎。通過該技術可以實現物件的共享,從而減少了記憶體的總體佔用量。除此之外,逃逸分析與棧上分配等優化技術也是降低了垃圾回收器,這樣一來java堆區不在是java物件分配的唯一地方了。

    儲存在jvm中的java物件可以劃分為兩類,一類是生命週期較短的物件,該類物件建立和消亡非常快速,相反另外的一類物件生命週期非常長,在某些極端情況下可能和虛擬機器生命週期一樣長,因此對於這些不同的物件應該採取不同的回收方法。目前所有的垃圾回收都是採用分代演算法,所以在堆區應該在劃分為新生代和老年代,新生代又分為Eden 和 FROM Survivor和To Survivor。既然java堆區用於儲存java物件的例項,那麼堆的大小在虛擬機器啟動時就設定好啦,可以通過Xms設定最小堆區 Xmx最大堆區。一旦堆區的記憶體大小超多最大堆區會丟擲OutOfMemoryError

2,方法區

   方法區和堆區一樣是允許被所有執行緒共享訪問,方法區儲存了每一個java類的結構資訊,比如執行時常量池,欄位和方法資料,建構函式和普通方法的位元組碼內容以及類,例項,介面初始化時需要的特殊方法等資料,儘管虛擬機器規範對方法區的具體實現的方法並沒有就具體說明但是在HotSpot中,方法區僅僅只是邏輯上的獨立,實際還是被包含在java堆區內,也就是說物理上屬於java堆區的一部分。

    方法區在虛擬機器啟動時被建立,並且它的實際的記憶體空間和java堆區一樣可以是不連續的。方法區是一塊比較特殊的執行時記憶體區,有一些開發人員更願意將方法區稱為永久區,這是主要因為方法區除了可以通多選項-XX MaxPermSize設定記憶體大小進行動態擴除外,並不會像java堆區那樣頻繁的被gc執行回收,設定還可以顯式的制定是否需要在程式執行時回收方法區中的資料。如果沒有顯式要求不對方法區記憶體回收的情況,gc的回收目標僅針對方法區中的常量池資訊和型別解除安裝。方法區也可能出現OutOfMemoryError。條件是出現記憶體大小超多-XX MaxPermSize

3.執行時常量池屬於方法區的一部分,也可能OutOfMemoryError

執行緒私有記憶體

1.pc暫存器

     由於虛擬機器是基於棧的結構,所有任何的操作都需要入棧和出棧,虛擬機器的pc暫存器並非廣義的物理暫存器,應該是pc暫存器,pc暫存器是對物理pc暫存器的一種抽象模擬,他是執行緒私有的,生命週期與執行緒的生命週期一樣,

如果當前執行緒所執行的是一個java方法,那麼暫存器機會儲存正在執行的位元組碼指令地址,反之如果是本地方法那麼就是指向null,就是暫存器值是空未定義。

  暫存器為什麼設計為執行緒私有?

  我們知道所謂的多執行緒在一個指定的時間段裡只會執行某一個執行緒的方法,CPU不停切換任務,那麼為了能夠準備的記錄各個執行緒正在執行的當前的位元組碼指令的地址,那麼就設計為執行緒私有每個執行緒都分配一個暫存器,這樣各個執行緒獨自記錄不會干擾。這是java虛擬機器唯一一個沒有宣告OutOfMemoryError的記憶體區。

2.java棧

   在虛擬機器規範中,執行緒私有,生命週期與執行緒的生命週期一樣.用於儲存棧幀,而棧幀就是存著區域性變量表,運算元棧,以及方法出口資訊等.

  java堆區既然存在的是物件例項,那麼棧區中的區域性變量表就是用於儲存個類原始資料型別,物件引用,以及返回型別.如果遞迴深度過深會丟擲OutOfMemoryError

3,本地方法棧

      這塊用c++實現