程序猿的平常——JVM內存模型與垃圾回收

Java開發有個很基礎的問題,雖然咱們平時接觸的很少,可是瞭解它卻成爲Java開發的必備基礎——這就是JVM。在C++中咱們須要手動申請內存而後釋放內存,不然就會出現對象已經再也不使用內存卻仍被佔用的狀況。在Java中JVM內置了垃圾回收的機制,幫助開發者承擔對象的建立和釋放的工做,極大的減輕了開發的負擔。那是否是咱們就不須要了解JVM了,顯然在作一些優化或者深刻研究應用性能的時候,JVM仍是起了很關鍵的做用的。所以本篇就總結性的描述下JVM的內存模型與垃圾回收相關的知識。html

本文的主要內容以下:java

  • 內存模型
  • 垃圾回收
  • 參考文章

內存模型

各部分的功能

這幾個存儲區最主要的就是棧區和堆區,那麼什麼是棧什麼是堆呢?說的簡單點,棧裏面存放的是基本的數據類型和引用,而堆裏面則是存放各類對象實例的。
算法

堆與棧分開設計是爲何呢?多線程

  • 棧存儲了處理邏輯、堆存儲了具體的數據,這樣隔離設計更爲清晰
  • 堆與棧分離,使得堆能夠被多個棧共享。
  • 棧保存了上下文的信息,所以只能向上增加;而堆是動態分配

棧的大小能夠經過-XSs設置,若是不足的話,會引發java.lang.StackOverflowError的異常併發

棧區

線程私有,生命週期與線程相同。每一個方法執行的時候都會建立一個棧幀(stack frame)用於存放 局部變量表、操做棧、動態連接、方法出口。性能

存放對象實例,全部的對象的內存都在這裏分配。垃圾回收主要就是做用於這裏的。優化

  • 堆得內存由-Xms指定,默認是物理內存的1/64;最大的內存由-Xmx指定,默認是物理內存的1/4。
  • 默認空餘的堆內存小於40%時,就會增大,直到-Xmx設置的內存。具體的比例能夠由-XX:MinHeapFreeRatio指定
  • 空餘的內存大於70%時,就會減小內存,直到-Xms設置的大小。具體由-XX:MaxHeapFreeRatio指定。

所以通常都建議把這兩個參數設置成同樣大,能夠避免JVM在不斷調整大小。.net

程序計數器

這裏記錄了線程執行的字節碼的行號,在分支、循環、跳轉、異常、線程恢復等都依賴這個計數器。線程

方法區

類型信息、字段信息、方法信息、其餘信息設計

總結

名稱 特徵 做用 配置 異常
棧區 線程私有,使用一段連續的內存空間 存放局部變量表、操做棧、動態連接、方法出口 -XSs StackOverflowError OutOfMemoryError
線程共享,生命週期與虛擬機相同 保存對象實例 -Xms -Xmx -Xmn OutOfMemoryError
程序計數器 線程私有、佔用內存小 字節碼行號
方法區 線程共享 存儲類加載信息、常量、靜態變量等 -XX:PermSize -XX:MaxPermSize OutOfMemoryError

垃圾回收

如何定義垃圾

有兩種方式,一種是引用計數(可是沒法解決循環引用的問題);另外一種就是可達性分析。

判斷對象能夠回收的狀況:

  • 顯示的把某個引用置位NULL或者指向別的對象
  • 局部引用指向的對象
  • 弱引用關聯的對象

垃圾回收的方法

Mark-Sweep標記-清除算法

這種方法優勢就是減小停頓時間,可是缺點是會形成內存碎片。

Copying複製算法

這種方法不涉及到對象的刪除,只是把可用的對象從一個地方拷貝到另外一個地方,所以適合大量對象回收的場景,好比新生代的回收。

Mark-Compact標記-整理算法

這種方法能夠解決內存碎片問題,可是會增長停頓時間。

Generational Collection 分代收集

最後的這種方法是前面幾種的合體,即目前JVM主要採起的一種方法,思想就是把JVM分紅不一樣的區域。每種區域使用不一樣的垃圾回收方法。

上面能夠看到堆分紅兩個個區域:

  • 新生代(Young Generation):用於存放新建立的對象,採用複製回收方法,若是在s0和s1之間複製必定次數後,轉移到年老代中。這裏的垃圾回收叫作minor GC;
  • 年老代(Old Generation):這些對象垃圾回收的頻率較低,採用的標記整理方法,這裏的垃圾回收叫作 major GC。

這裏能夠詳細的說一下新生代複製回收的算法流程:

在新生代中,分爲三個區:Eden, from survivor, to survior。

  • 當觸發minor GC時,會先把Eden中存活的對象複製到to Survivor中;
  • 而後再看from survivor,若是次數達到年老代的標準,就複製到年老代中;若是沒有達到則複製到to survivor中,若是to survivor滿了,則複製到年老代中。
  • 而後調換from survivor 和 to survivor的名字,保證每次to survivor都是空的等待對象複製到那裏的。

垃圾回收器

串行收集器 Serial

這種收集器就是以單線程的方式收集,垃圾回收的時候其餘線程也不能工做。

並行收集器 Parallel

以多線程的方式進行收集

併發標記清除收集器 Concurrent Mark Sweep Collector, CMS

大體的流程爲:初始標記--併發標記--從新標記--併發清除

G1收集器 Garbage First Collector

大體的流程爲:初始標記--併發標記--最終標記--篩選回收

參考

相關文章
相關標籤/搜索