Java GC機制及原理 項目實際遇到GC問題解決思路和經驗總結

1.什麼是GC及基礎知識介紹

GC(Garbage Collection) 簡稱垃圾收集 垃圾回收html

JVM運行時數據區:java

1.方法區存儲類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯後的代碼等算法

2.堆(heap)存儲對象的信息,分爲新生代(Eden,Survivor1,Survivor2)和老年代,永久代apache

3.程序計數器,存儲的數據所佔空間的大小不會隨程序的執行而發生改變,所以,對於程序計數器是不會發生內存溢出現象(OutOfMemory)的瀏覽器

4.Java棧(stack)是Java方法執行的內存模型tomcat

5.本地方法棧則是爲執行本地方法(Native Method)服務的app

 

2. 垃圾回收策略

講到垃圾回收,那麼何時對象須要回收,如何去判斷對象是存活仍是死亡,咱們採用引用計數法來判斷對象是否存活,當一個對象被引用時,計數器值加1,當引用失效時減1.less

強引用與弱引用的區別:eclipse

強引用:相似Object obj = new Object();只要強引用還存在,垃圾回收器不會收集被引用的對象jvm

軟引用:用來描述還有用但非必需的對象

經過可達性分析算法來判斷對象是否須要被回收

垃圾回收策略有 標記清除法(會產生過多的內存碎片),複製法(內存使用率不高),標記整理法

垃圾收集器分類

Serial收集器:發展歷史最悠久的收集器

ParNew收集器

Minor GC & Major GC & Full GC

從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱爲 Minor GC

  • Major GC 是清理老年代內存
  • Minor GC 是清理年輕代(Eden和Survivor區域)內存
  • Full GC 是清理整個堆空間—包括年輕代和永久代

CMS(Concurrent Mark Sweep)收集器:是一種以獲取最短停頓時間爲目標的垃圾收集器

 

3.GC問題經常使用命令介紹

jps(Java Virtual Machine Process Status Tool);//虛擬機進程情況工具
jstat;//虛擬機統計信息監視工具
jstat -gcutil 19473;//統計gc信息
jstat -gc 4588 250 20;//每250毫秒查詢進程4588垃圾收集狀況 一共查詢20次
jstat -gcold 4588;//查看老年代gc存儲量
jstat -gcnew 4588;//查看年輕代gc存儲量

-gc:監視堆內存狀況,包括eden區,s1,s2,老年代和永久代的內存容量
-gcnew:監視新生代GC狀況
-gcold:監視老年代GC狀況

jinfo;//Java配置信息工具
jmap;//java內存映像工具

使用jmap生成dump文件
jmap -dump:format=b,file=eclipse.bin 14949;//14949進程號
jhat;//虛擬機堆轉儲快照分析工具
jstack;//java堆棧跟蹤工具

 

關於GC重要命令介紹

關於jps

jps是用於查詢jvm進程信息的

主要參數有:

-q 不輸出類名、Jar名和傳入main方法的參數
-m 輸出傳入main方法的參數
-l 輸出main類或Jar的全限名
-v 輸出傳入JVM的參數

好比輸入

jps -m -l

會顯示下面的信息

15089 org.apache.catalina.startup.Bootstrap start
27362 org.apache.catalina.startup.Bootstrap start
9043 org.apache.catalina.startup.Bootstrap start
9765 sun.tools.jps.Jps -m -l
8328 org.apache.catalina.startup.Bootstrap start
27179 org.apache.zookeeper.server.quorum.QuorumPeerMain /usr/local/zookeeper-3.4.6/bin/../conf/zoo.cfg
31454 org.apache.catalina.startup.Bootstrap start


關於jstack

  jstack主要用來查看某個Java進程內的線程堆棧信息

jstack -F 2881

 

主要參數有:

-F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m  不只會輸出Java堆棧信息,還會輸出C/C++堆棧信息(好比Native方法)
-l  會打印出額外的鎖信息,在發生死鎖時能夠用jstack -l pid來觀察鎖持有狀況
-h or -help to print this help message

關於jmap

 jmap用來查看堆內存使用情況,通常結合jhat使用

jmap -heap 7481
jmap -histo:live 1432 | more;//查看堆內存中的對象數目、大小統計直方圖,若是帶上live則只統計活對象
jmap -permstat 7481;//若是操做系統是64位

 打印進程的類加載器和類加載器加載的持久代對象信息,輸出:類加載器名稱、對象是否存活(不可靠)、對象地址、父類加載器、已加載的類大小等信息

使用jmap -heap pid查看進程堆內存使用狀況,包括使用的GC算法、堆配置參數和各代中堆內存使用狀況

[root@localhost ~]# jmap -heap 7481
Attaching to process ID 7481, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.76-b04

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 0
   MaxHeapFreeRatio = 100
   MaxHeapSize      = 1981808640 (1890.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 31981568 (30.5MB)
   used     = 11806536 (11.259590148925781MB)
   free     = 20175032 (19.24040985107422MB)
   36.916689012871416% used
From Space:
   capacity = 4718592 (4.5MB)
   used     = 0 (0.0MB)
   free     = 4718592 (4.5MB)
   0.0% used
To Space:
   capacity = 4718592 (4.5MB)
   used     = 0 (0.0MB)
   free     = 4718592 (4.5MB)
   0.0% used
PS Old Generation
   capacity = 82313216 (78.5MB)
   used     = 0 (0.0MB)
   free     = 82313216 (78.5MB)
   0.0% used
PS Perm Generation
   capacity = 22020096 (21.0MB)
   used     = 5066136 (4.831443786621094MB)
   free     = 16953960 (16.168556213378906MB)
   23.00687517438616% used

2942 interned Strings occupying 249928 bytes.

 

 一個很經常使用的狀況是:用jmap把進程內存使用狀況dump到文件中,再用jhat分析查看。jmap進行dump命令格式以下:

jmap -dump:format=b,file=dumpFileName pid

jmap -dump:format=b,file=/tmp/dump.dat 21711 

jmap -dump:live,format=b,file=xxx 2657

 

用jhat分析dump文件:

jhat -port 9998 /tmp/dump.dat

瀏覽器端輸入http://localhost:9998 能夠看到下面的頁面:

關於jstat

jstat(JVM統計監測工具)

jstat -gc 21711 250 4;//輸出的是GC信息,採樣時間間隔爲250ms,採樣數爲4

輸入內容爲:

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1024.0 1024.0  0.0   544.1  28672.0  23313.6   142336.0   98745.4   57984.0 55759.5 7040.0 6445.8   1213    8.115   3      0.322    8.437
1024.0 1024.0  0.0   544.1  28672.0  23313.6   142336.0   98745.4   57984.0 55759.5 7040.0 6445.8   1213    8.115   3      0.322    8.437
1024.0 1024.0  0.0   544.1  28672.0  23315.6   142336.0   98745.4   57984.0 55759.5 7040.0 6445.8   1213    8.115   3      0.322    8.437
1024.0 1024.0  0.0   544.1  28672.0  23317.7   142336.0   98745.4   57984.0 55759.5 7040.0 6445.8   1213    8.115   3      0.322    8.437

 

要明白上面各列的意義,先看JVM堆內存佈局:

能夠看出:

堆內存 = 年輕代 + 年老代 + 永久代
年輕代 = Eden區 + 兩個Survivor區(From和To)

 

如今來解釋各列含義:

S0C、S1C、S0U、S1U:Survivor 0/1區容量(Capacity)和使用量(Used)
EC、EU:Eden區容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年輕代GC次數和GC耗時
FGC、FGCT:Full GC次數和Full GC耗時
GCT:GC總耗時

 

JVM參數含義

-Xms 是指設定程序啓動時佔用內存大小,通常來說,大點,程序會啓動的 快一點,可是也可能會致使機器暫時間變慢。

-Xmx 是指設定程序運行期間最大可佔用的內存大小。若是程序運行須要佔 用更多的內存,超出了這個設置值,就會拋出OutOfMemory 異常。

-Xss 是指設定每一個線程的堆棧大小。這個就要依據你的程序,看一個線程 大約須要佔用多少內存,可能會有多少線程同時運行等。

-Xmn 新生代大小

tomcat內存設置

CATALINA_OPTS="$CATALINA_OPTS -server -Djava.awt.headless=true -Xms5000m -Xmx5000m -Xss256k -XX:PermSize=128m -XX:MaxPermSize=384m -XX:NewSize=4000m -XX:MaxNewSize=4000m -XX:SurvivorRatio=22 -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:-ReduceInitialCardMarks -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -Xloggc:/data/applogs/heap_trace.txt -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/applogs/HeapDumpOnOutOfMemoryError"

CATALINA_OPTS="$CATALINA_OPTS -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8"

CATALINA_OPTS="$CATALINA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"

 

tomcat啓動參數參考

-Xms20288m -Xmx20288m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:NewSize=10144m -XX:MaxNewSize=10144m -XX:SurvivorRatio=10

 

標準配置參考配置catalina.sh(http://www.cnblogs.com/oskyhg/p/6549877.html)

CATALINA_OPTS="$CATALINA_OPTS -server -Djava.awt.headless=true -Xms5000m -Xmx5000m -Xss256k -XX:PermSize=128m -XX:MaxPermSize=384m -XX:NewSize=4000m -XX:MaxNewSize=4000m -XX:SurvivorRatio=22 -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:-ReduceInitialCardMarks -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -Xloggc:/data/applogs/heap_trace.txt -XX:-HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/applogs/HeapDumpOnOutOfMemoryError"

CATALINA_OPTS="$CATALINA_OPTS -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8"

重要概念

-Xmx10240m:表明最大堆

-Xms10240m:表明最小堆

-Xmn5120m:表明新生代

-XXSurvivorRatio=3:表明Eden:Survivor= 3 根據Generation-Collection算法(目前大部分JVM採用的算法),通常根據對象的生存週期將堆內存分爲若干不一樣的區域,通常狀況將新生代分爲Eden,兩塊Survivor;
計算Survivor大小分別比爲3:1:1,Eden:Survivor =3,總大小爲5120,3x+x+x=5120  x=1024

新生代大部分要回收,採用Copying算法,快!

老年代
大部分不須要回收,採用Mark-Compact算法- 標記清除算法

 

4.JVM性能調試工具

經常使用的JVM調試工具備visualvm(http://visualvm.java.net/),heap analyzer 

相關文章
相關標籤/搜索