jvm知識點摘抄

前言

物理計算機(多cpu)的結構

如上圖所示,基於高速緩存的存儲交互很好的解決了處理器與內存之間的矛盾,也引入了新的問題:緩存一致性問題。在多處理器系統中,每個處理器有自己的高速緩存,而他們又共享同一塊內存(下文成主存,main memory 主要內存),當多個處理器運算都涉及到同一塊內存區域的時候,就有可能發生緩存不一致的現象。爲了解決這一問題,需要各個處理器運行時都遵循一些協議,在運行時需要將這些協議保證數據的一致性。這類協議包括MSI、MESI、MOSI、Synapse、Firely、DragonProtocol等。

 

虛擬機內存模型

虛擬機內存模型中定義的訪問操作與物理計算機處理的基本一致!

如上圖所示,Java中通過多線程機制使得多個任務同時執行處理,所有的線程共享JVM內存區域main memory,而每個線程又單獨的有自己的工作內存,當線程與內存區域進行交互時,數據從主存拷貝到工作內存,進而交由線程處理(操作碼+操作數)。

 

一、jvm結構

1.1、整體結構

整體如下圖所示:

 

如圖所示,JVM主要包括四個部分:

1.類加載器(ClassLoader):在JVM啓動時或者在類運行時將需要的class加載到JVM中。(右圖表示了從java源文件到JVM的整個過程,可配合理解。 關於類的加載機制,可以參考http://blog.csdn.net/tonytfjing/article/details/47212291

2.執行引擎:負責執行class文件中包含的字節碼指令(執行引擎的工作機制,這裏也不細說了,這裏主要介紹JVM結構);

3.內存區(也叫運行時數據區):是在JVM運行的時候操作所分配的內存區。

4.本地方法接口:主要是調用C或C++實現的本地方法及返回結果。

 

1.2、內存區

如圖所示,內存區包括以下幾個部分:

  • 方法區(Method Area):用於存儲類結構信息的地方,包括常量池、靜態變量、構造函數等。雖然JVM規範把方法區描述爲堆的一個邏輯部分, 但它卻有個別名non-heap(非堆),所以大家不要搞混淆了。方法區還包含一個運行時常量池。

  • java堆(Heap):存儲java實例或者對象的地方。這塊是GC的主要區域(後面解釋)。從存儲的內容我們可以很容易知道,方法區和堆是被所有java線程共享的。
  • java棧(Stack):java棧總是和線程關聯在一起,每當創建一個線程時,JVM就會爲這個線程創建一個對應的java棧。在這個java棧中又會包含多個棧幀,每運行一個方法就創建一個棧幀,用於存儲局部變量表、操作棧、方法返回值等。每一個方法從調用直至執行完成的過程,就對應一個棧幀在java棧中入棧到出棧的過程。所以java棧是現成私有的。
  • 程序計數器(PC Register):用於保存當前線程執行的內存地址。由於JVM程序是多線程執行的(線程輪流切換),所以爲了保證線程切換回來後,還能恢復到原先狀態,就需要一個獨立的計數器,記錄之前中斷的地方,可見程序計數器也是線程私有的。
  • 本地方法棧(Native Method Stack):和java棧的作用差不多,只不過是爲JVM使用到的native方法服務的。

 

1.3、堆

年輕代:是所有新對象產生的地方。年輕代被分爲3個部分——Eden區和兩個Survivor區(From和to)。當Eden區被對象填滿時,就會執行Minor GC。並把所有存活下來的對象轉移到其中一個survivor區(假設爲from區)。Minor GC同樣會檢查存活下來的對象,並把它們轉移到另一個survivor區(假設爲to區)。這樣在一段時間內,總會有一個空的survivor區。經過多次GC週期後,仍然存活下來的對象會被轉移到年老代內存空間。通常這是在年輕代有資格提升到年老代前通過設定年齡閾值來完成的。需要注意,Survivor的兩個區是對稱的,沒先後關係,from和to是相對的。

年老代:在年輕代中經歷了N次回收後仍然沒有被清除的對象,就會被放到年老代中,可以說他們都是久經沙場而不亡的一代,都是生命週期較長的對象。對於年老代和永久代,就不能再採用像年輕代中那樣搬移騰挪的回收算法,因爲那些對於這些回收戰場上的老兵來說是小兒科。通常會在老年代內存被佔滿時將會觸發Full GC,回收整個堆內存。

永久代:永久帶又叫Perm區,只存在於hotspot jvm中,並且只存在於jdk7和之前的版本中,jdk8中已經徹底移除了永久帶,jdk8中引入了一個新的內存區域叫metaspace。

(1)並不是所有的jvm中都有永久帶,ibm的j9,oracle的JRocket都沒有永久帶。

(2)永久帶是實現層面的東西。

(3)永久帶裏面存的東西基本上就是方法區規定的那些東西。

因此,我們可以說,永久帶是方法區的一種實現,當然,在hotspot jdk8中metaspace可以看成是方法區的一種實現。

hotspot jdk8中移除了永久帶以後的內存結構:

 

1.4 垃圾回收

 

二、垃圾回收

垃圾收集器一般必須完成兩件事:檢測出垃圾;回收垃圾。

2.1 如何檢測

引用計數法:給一個對象添加引用計數器,每當有個地方引用它,計數器就加1;引用失效就減1。

可達性分析算法:以根集對象爲起始點進行搜索,如果有對象不可達的話,即是垃圾對象。這裏的根集一般包括java棧中引用的對象、方法區常量池中引用的對象、本地方法中引用的對象等。

 

2.2 如何回收

1.標記-清除(Mark-sweep)

2.複製(Copying)

3.標記-整理(Mark-Compact)

4.分代收集算法

這是當前商業虛擬機常用的垃圾收集算法。分代的垃圾回收策略,是基於這樣一個事實:不同的對象的生命週期是不一樣的。因此,不同生命週期的對象可以採取不同的收集方式,以便提高回收效率。

 

三、參考文章
JVM內存結構,爲什麼需要GC?
深入理解JVM—JVM內存模型
JVM的方法區和永久代的關係

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章