深入理解java虛擬機(七):java垃圾收集分析總結

一、垃圾回收觸發條件

  1、Minor gc觸發條件

當新生代空間不足時會主動觸發Minor gc,並且自動擴容(可通過控制使新生代直接處於最大內存空間,避免自動擴容和垃圾收集)。

  2、Full gc觸發條件

和新生代一樣,當老年代空間不足時會觸發Full gc,並且自動擴容;另外當在代碼中調用System.gc()時也會觸發Full gc。 可通過參數-XX:+DisableExplicitGC 控制使System.gc()失效。

  3、永久待觸發條件

類似上面,當永久待空間不足時,會發出Full gc,可通過控制PermSize=MaxPermSize 避免自動擴容和垃圾回收。另外可通過參數-Xnoclassgc 來控制虛擬機不對(永久待類對象)進行回收。

二、Runtime.exec創建新進程(內存疊加)佔用外部內存

java虛擬機執行Runtime.exec 的過程是:首先克隆一個和當前虛擬機擁有一樣環境變量的進程,再用這個心的進程區執行外部命令,最後再退出這個進程
 如果頻繁執行,系統的消耗會很大,不僅是cpu還有內存。
 另外這個時候要注意了,在採集java程序的內存時,一定要注意有java程序通過Runtime.exec創建的新進程所佔用的內存,按理來說,java創建的新進程所佔用的內存也應該歸屬於這個java程序的內存。
 例:下面是在redhat下面用java程序通過Runtime.exec執行shell腳本。

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;


public class TestSleep {

        public static void main(String[] args) {
                System.out.println("being sleep"+new Date().toLocaleString());
                try
                {
                Runtime rt = Runtime.getRuntime();
                Process proc = rt.exec("/home/boco/script/sleep.sh");
                InputStream stdin = proc.getInputStream();
                InputStreamReader isr = new InputStreamReader(stdin);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                System.out.println("output");
                while ( (line = br.readLine()) != null)
                System.out.println(line);
                System.out.println("");
                int exitVal = proc.waitFor();
                System.out.println("Process exitValue: " + exitVal);
                } catch (Throwable t)
                {
                t.printStackTrace();
                }

                System.out.println("end sleep"+new Date().toLocaleString());
        }
}

shell腳本內容:

#!/bin/bash
echo "begin"
sleep 10
echo "end"


執行結果:


 可以看出有java進程產生了一個子進程,即shell腳本,而這個shell腳本又產生了一個子進程,即sleep。

三、類加載-字節碼驗證時間

 類加載時間虛擬機加載類所耗掉的總時間
 字節碼驗證會耗掉一部分時間,在保證字節碼是安全的情況下,可以通過參數 -Xverify:none禁止掉字節碼驗證過程。

 

 

 

四、編譯時間

編譯時間指虛擬機的JIT編譯器(Just in time Compiler)編譯熱點代碼(Hot Spot Code)的耗時

我們知道java語言爲了實現跨平臺的特性, java代碼編譯出來後形成的class文件中存儲的是字節碼(ByteCode),虛擬機通過解釋方式執行字節碼命令,比起c語言的編譯執行速度要慢不少。 不過在java1.2後,虛擬機內置了2個運行期間編譯器(代號爲C1和C2,C1在client模式下啓用,C2在server模式下啓用),如果一個java方法被調用數次到一定程度就會被判定爲熱代碼交個JIT編譯器編譯爲本地代碼, 提高運行速度,這就是hotspot虛擬機名字的由來
編譯時間總長即爲編譯熱代碼所消耗的時間總和。

五、垃圾收集打印參數

 -XX:+PrintGCApplicationStoppedTime 參數打印gc停頓時間
 -XX:+PrintGCDateStamps  參數打印gc時間戳,系統時間
 -XX:+PrintGCTimeStamps 參數打印gc時間,相對於jvm啓動時間
 -Xloggc:gclog.log  設置gc日誌文件
 -XX:+PrintReferenceGC  打印gc引用
 -XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中斷的執行時間
 -XX:+PrintHeapAtGC 打印GC前後的詳細堆棧信息

 

例:

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -Xloggc:gclog.log -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC

輸出gclog.log:

 


Application time: 0.0055586 seconds
{Heap before GC invocations=0 (full 0):
 def new generation   total 9216K, used 6487K [0x32750000, 0x33150000, 0x33150000)
  eden space 8192K,  79% used [0x32750000, 0x32da5fd0, 0x32f50000)
  from space 1024K,   0% used [0x32f50000, 0x32f50000, 0x33050000)
  to   space 1024K,   0% used [0x33050000, 0x33050000, 0x33150000)
 tenured generation   total 10240K, used 0K [0x33150000, 0x33b50000, 0x33b50000)
   the space 10240K,   0% used [0x33150000, 0x33150000, 0x33150200, 0x33b50000)
 compacting perm gen  total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
   the space 12288K,   3% used [0x33b50000, 0x33bae748, 0x33bae800, 0x34750000)
    ro space 10240K,  55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
    rw space 12288K,  55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
2014-02-26T15:44:05.625+0800: 0.049: [GC 0.049: [DefNew: 6487K->151K(9216K), 0.0040768 secs] 6487K->6295K(19456K), 0.0041381 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap after GC invocations=1 (full 0):
 def new generation   total 9216K, used 151K [0x32750000, 0x33150000, 0x33150000)
  eden space 8192K,   0% used [0x32750000, 0x32750000, 0x32f50000)
  from space 1024K,  14% used [0x33050000, 0x33075ee8, 0x33150000)
  to   space 1024K,   0% used [0x32f50000, 0x32f50000, 0x33050000)
 tenured generation   total 10240K, used 6144K [0x33150000, 0x33b50000, 0x33b50000)
   the space 10240K,  60% used [0x33150000, 0x33750030, 0x33750200, 0x33b50000)
 compacting perm gen  total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
   the space 12288K,   3% used [0x33b50000, 0x33bae748, 0x33bae800, 0x34750000)
    ro space 10240K,  55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
    rw space 12288K,  55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
}
Total time for which application threads were stopped: 0.0043639 seconds
Heap
 def new generation   total 9216K, used 4575K [0x32750000, 0x33150000, 0x33150000)
  eden space 8192K,  54% used [0x32750000, 0x32ba1fa8, 0x32f50000)
  from space 1024K,  14% used [0x33050000, 0x33075ee8, 0x33150000)
  to   space 1024K,   0% used [0x32f50000, 0x32f50000, 0x33050000)
 tenured generation   total 10240K, used 6144K [0x33150000, 0x33b50000, 0x33b50000)
   the space 10240K,  60% used [0x33150000, 0x33750030, 0x33750200, 0x33b50000)
 compacting perm gen  total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
   the space 12288K,   3% used [0x33b50000, 0x33bae748, 0x33bae800, 0x34750000)
    ro space 10240K,  55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
    rw space 12288K,  55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
Application time: 0.0007510 seconds
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章