Java分代垃圾回收機制:年輕代/年老代/持久代(轉)

angou6476發表於2017-09-07

虛擬機器中的共劃分為三個代:年輕代(Young Generation)年老點(Old Generation)持久代(Permanent Generation)。其中持久代主要存放的是Java類的類資訊,與垃圾收集要收集的Java物件關係不大。年輕代和年老代的劃分是對垃圾收集影響比較大的。

年輕代:

所有新生成的物件首先都是放在年輕代的。年輕代的目標就是儘可能快速的收集掉那些生命週期短的物件。年輕代分三個區。一個Eden區,兩個Survivor區(一般而言)。大部分物件在Eden區中生成。當Eden區滿時,還存活的物件將被複制到Survivor區(兩個中的一個),當這個Survivor區滿時,此區的存活物件將被複制到另外一個Survivor區,當這個Survivor去也滿了的時候,從第一個Survivor區複製過來的並且此時還存活的物件,將被複制“年老區(Tenured)”。需要注意,Survivor的兩個區是對稱的,沒先後關係,所以同一個區中可能同時存在從Eden複製過來物件,和從前一個Survivor複製過來的物件,而複製到年老區的只有從第一個Survivor去過來的物件。而且,Survivor區總有一個是空的。同時,根據程式需要,Survivor區是可以配置為多個的(多於兩個),這樣可以增加物件在年輕代中的存在時間,減少被放到年老代的可能。

年老代:

在年輕代中經歷了N次垃圾回收後仍然存活的物件,就會被放到年老代中。因此,可以認為年老代中存放的都是一些生命週期較長的物件。

持久代:

用於存放靜態檔案,如今Java類、方法等。持久代對垃圾回收沒有顯著影響,但是有些應用可能動態生成或者呼叫一些Class,例如Hibernate等,在這種時候需要設定一個比較大的持久代空間來存放這些執行過程中新增的類。持久代大小通過-XX:MaxPermSize=<N>進行設定。

什麼情況下觸發垃圾回收:

由於物件進行了分代處理,因此垃圾回收區域、時間也不一樣。GC有兩種型別:Scavenge GC和Full GC。

Scavenge GC

一般情況下,當新物件生成,並且在Eden申請空間失敗時,就會觸發Scavenge GC,對Eden區域進行GC,清除非存活物件,並且把尚且存活的物件移動到Survivor區。然後整理Survivor的兩個區。這種方式的GC是對年輕代的Eden區進行,不會影響到年老代。因為大部分物件都是從Eden區開始的,同時Eden區不會分配的很大,所以Eden區的GC會頻繁進行。因而,一般在這裡需要使用速度快、效率高的演算法,使Eden去能儘快空閒出來。

Full GC

對整個堆進行整理,包括Young、Tenured和Perm。Full GC因為需要對整個對進行回收,所以比Scavenge GC要慢,因此應該儘可能減少Full GC的次數。在對JVM調優的過程中,很大一部分工作就是對於FullGC的調節。有如下原因可能導致Full GC:

  • 年老代(Tenured)被寫滿
  • 持久代(Perm)被寫滿
  • System.gc()被顯示呼叫
  • 上一次GC之後Heap的各域分配策略動態變化

 

參考:

http://jefferent.iteye.com/blog/1123677(以上內容轉自此篇文章)

轉載於:https://www.cnblogs.com/EasonJim/p/7489922.html

相關文章