1. 程式人生 > >GC知識點

GC知識點

一、判斷物件是否存活

1、引用計數法

2、可達性分析

就是通過一系列的稱為“GC Roots”的物件作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鏈(Reference Chain),當一個物件到GC Roots沒有任何引用鏈相連,則證明此物件是不可用的。

GC Root引用點:

a、JavaStack (棧楨中的本地變量表)中的引用的物件。

b、方法區中靜態引用指向的物件。

c、方法區中常量引用指向的物件。

d、Native方法中JNI引用的物件

二、回收演算法

1、複製(Copying)

2、標記-清除(Mark-Sweep)

3、標記-整理(Mark-Compact)

三、安全點(Safe Point)

程式只有在到達安全點時才能暫停。安全點的選定標準是“是否具有讓程式長時間執行的特徵”。“長時間執行”的最明顯特徵就是指令序列的複用,如方法呼叫、迴圈跳轉等,具有這些功能的指令才會產生安全點。

讓程式暫停的兩種方式:

搶先式中斷(Preemptive Suspension):在GC發生時,主動中斷所有執行緒,不需要執行緒執行的程式碼主動配合。幾乎不被採用。

主動式中斷(Voluntary Suspension):設一個標誌,各個執行緒主動去輪詢這個標誌,遇到中斷則暫停。輪詢地方與安全點重合。

四、Full GC

從年輕代空間(包括 Eden 和 Survivor 區域)回收記憶體被稱為 Minor GC,對老年代GC稱為Major GC,而Full GC是對整個堆來說的,在最近幾個版本的JDK裡預設包括了對永生代即方法區的回收(JDK8中無永生帶了),出現Full GC的時候經常伴隨至少一次的Minor GC,但非絕對的。Major GC的速度一般會比Minor GC慢10倍以上。下邊看看有那種情況觸發JVM進行Full GC及應對策略。

1、System.gc()
此方法是建議JVM進行Full GC而非一定,但很多情況下它會觸發 Full GC,從而增加Full GC的頻率,也即增加了間歇性停頓的次數。強烈建議禁止此方法,讓虛擬機器自己去管理它的記憶體,可通過-XX:+ DisableExplicitGC來禁止RMI調System.gc。

2、老年代空間不足
老年代空間只有在新生代物件轉入及建立大物件、大陣列時才會出現不足的現象,當執行Full GC後空間仍然不足,則丟擲如下錯誤:
java.lang.OutOfMemoryError: Java heap space 

3、永生區空間不足
Permanet Generation中存放的為一些class的資訊、常量、靜態變數等資料,當系統中要載入的類、反射的類和呼叫的方法較多時,Permanet Generation可能會被佔滿,在未配置為採用CMS GC的情況下也會執行Full GC。如果經過Full GC仍然回收不了,那麼JVM會丟擲如下錯誤資訊:java.lang.OutOfMemoryError: PermGen space 

4、CMS GC時出現promotion failed和concurrent mode failure

 

五、JAVA OPTS標準

-server

記憶體配置
-Xms2g -Xmx2g -Xmn768m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m

GC配置
-XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent 
-XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:CMSInitiatingOccupancyFraction=68 
-XX:+CMSClassUnloadingEnabled

GC日誌配置
-XX:+PrintGCDetails -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime 
-XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -Xloggc:/wls/applogs/rtlogs/server/gc.log -XX:+HeapDumpOnOutOfMemoryError 
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M

Dump配置
-XX:HeapDumpPath=/wls/applogs/rtlogs/server -XX:ErrorFile=/wls/applogs/rtlog/server/hs_err_pid%p.log

其他配置
-Djava.awt.headless=true -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider 
-Djava.security.egd=file:/dev/./urandom -Dsun.net.inetaddr.ttl=30 
-XX:SoftRefLRUPolicyMSPerMB=0

解決JDK7裡改變Sort演算法的問題
-Djava.util.Arrays.useLegacyMergeSort=true

日誌配置
(同步日誌)
-Dlog4j.configurationFile=META-INF/zues/zues-log4j2-include.xml,/wls/wls81/envconfig/busrecon-service/log4j2.xml

(非同步日誌)
-Dlog4j.configurationFile=META-INF/zues/zues-log4j2-async-include.xml,/wls/wls81/envconfig/busrecon-service/log4j2.xml

Dubbo配置檔案
-Ddubbo.properties.file=/wls/wls81/envconfig/busrecon-service/dubbo.properties

Spring Boot特有
-Dspring.config.name=env

字符集編碼(注意,應用是UTF8的才可以這麼寫)
-Ddefault.client.encoding=UTF-8 -Ddefault.override.encoding=UTF-8 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.region=CN

 

Ref:

https://my.oschina.net/hosee/blog/674261