JAVA分代垃圾回收機制測試

java分代回收測試
測試代碼:

package juint.test;

import java.util.HashMap;
import java.util.Map;


public class JstatTest
{
    
    @SuppressWarnings("static-access")
    public static void main(String[] args)
    {
        Map<String,Object> map=new HashMap<String,Object>();
        for(int i=0;i<1000000;i++){
            try
            {
                map.put(String.valueOf(i), new Integer(i));
                System.out.println("循環--"+new Integer(i));
                Thread.currentThread().sleep(10);//這裏可以調整爲500,50,10
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}
命令使用
jstat -gcutil 1300 1000 500


這裏補充一下,在此文的基礎上,基本多次YGC 對應一次FullGC,注意這裏只有兩個Survivor區,可以定義多個,數據如下:

 S0          S1      E        O          P     YGC     YGCT    FGC    FGCT     GCT

100.00   0.00  53.40  74.12   3.06     12         0.170     1        0.033    0.202 

這裏進行了12的YGC,也就是說在Survivor 複製了12次,FGC進行了一次,每一次YGC都會往Old中存放對象,一下是數據支持:

 S0          S1      E         O          P      YGC     YGCT    FGC    FGCT     GCT

  0.00    0.00   100.00   0.00     3.06      0        0.000     0       0.000       0.000
  0.00   100.00   4.02    5.94     3.06      1        0.013     0       0.000       0.013

最開始s0和s1都沒有,在進行一次YGC之後O裏面有內容了,實驗得知,每一次往S0或者S1複製對象,都會往old裏面添加添加存活較久的對象,並且FGC執行,不一定非得Old滿了,纔會進行,在第一組數據裏,FGC就進行了,但O區還只有74.12的數據

查看java虛擬機內存情況,也可以使用這個命令:java -stat


以下是原理,感謝  http://jefferent.iteye.com/blog/1123677 這裏貼上方便查看,也可以直接複製url上他的博客查看

虛擬機中的共劃分爲三個代:年輕代(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的各域分配策略動態變化
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章