中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java垃圾收集器的介紹以及JVM調優方法

發布時間:2021-09-04 21:52:15 來源:億速云 閱讀:172 作者:chen 欄目:大數據

這篇文章主要講解了“Java垃圾收集器的介紹以及JVM調優方法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java垃圾收集器的介紹以及JVM調優方法”吧!

垃圾收集器

1.Serial

關注點:stw的時間 復制算法 STW

2.ParNew

關注點:stw的時間 Serial的多線程版本 復制算法 STW

參數 -XX:ParallelGCThreads 并行線程數

3.Parallel Scavenge

關注點:達到一個可控制的吞吐量(吞吐量優先) 復制算法 所謂吞吐量就是CPU運行用戶代碼的時間和CPU消耗的時間的比值,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)。

Paralled Scavenge 收集器提供了兩個參數用于精確控制吞吐量。分別是控制最大垃圾收集停頓時間的-XX:MaxGCPauseMillis ,以及直接設置吞吐量大小的-XX:GCTimeRatio 參數。

參數

-XX:MaxGCPauseMillis 
-XX:GCTimeRatio
-XX:+UseAdaptiveSizePolicy 自適應調節策略

old區

1.Serial Old

Serial的老年代版本 
JDK1.5之前可搭配Parallel Scavenge使用
在CMS發生Concurrent mode failure時使用
Mark-Compact

2.Parallel Old

Parallel Scavenge的老年代版本
JDK1.6出現 搭配Parallel Scavenge使用
Mark-Compact

3.CMS

-XX:+UseConcMarkSweepGC
Mark-Sweep
過程:初始標記 并發標記 重新標記 并發清除
初始標記和重新標記會STW
耗時最長是并發標記和并發清除
默認回收線程數:CMS默認啟動的回收線程數目是 (ParallelGCThreads + 3)/4),可以通過-XX:ParallelCMSThreads=20來設定

優點:并發低停頓
缺點:
1、對CPU資源非常敏感 
占用部分線程(CPU資源)導致應用程序變慢,吞吐量降低
默認線程數=(CPU數量+3)/4
2、無法處理浮動垃圾,可能出現Concurrent mode failure而導致另一次fullGC的產生
參數-XX:CMSInitiatingOccupancyFraction默認68% CMS觸發百分比,CMS執行期間,預留空間無法滿足,就會出現Concurrent mode failure失敗,啟動后備SerialOld的方案,停頓時間更長了。(所以CMSInitiatingOccupancyFraction不能設置的過大)
3、內存碎片
參數-XX:+UseCMSCompactAtFullCollection(停頓時間加長) 默認開啟
-XX:CMSFullGCsBeforeCompaction(執行多少次不進行碎片整理的FullGC后進行一次帶壓縮的)

其他參數
初始標記的并行化-XX:+CMSParallelInitialMarkEnabled
為了減少第二次暫停的時間,開啟并行remark: -XX:+CMSParallelRemarkEnabled,如果remark還是過長的話,可以開啟-XX:+CMSScavengeBeforeRemark(在CMS GC前啟動一次ygc,目的在于減少old gen對ygc gen的引用,降低remark時的開銷-----一般CMS的GC耗時 80%都在remark階段)

為了避免Perm區滿引起的full gc,建議開啟CMS回收Perm區選項:
+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

-XX:+UseConcMarkSweepGC:設置年老代為并發收集。測試中配置這個以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此時年輕代大小最好用-Xmn設置。
-XX:+UseParNewGC:設置年輕代為并行收集。可與CMS收集同時使用。JDK5.0以上,JVM會根據系統配置自行設置,所以無需再設置此值。

G1收集器

收集器組合開關選項

-XX:+UseSerialGC Serial+SerialOld
-XX:+UseParNewGC ParNew+SerialOld
-XX:+UseParallelGC ParallelScavenge+SerialOld 
-XX:+UseConcMarkSweepGC ParNew+CMS+SerialOld  FullGC算法:單線程的Mark Sweep Compact(MSC)
-XX:+UseParallelOldGC ParallelScavenge+Parallel Old  FullGC算法:PS MarkSweep

JVM參數

垃圾回收參數
-Xnoclassgc 是否對類進行回收
-verbose:class -XX:+TraceClassUnloading 查看類加載和卸載信息

-XX:SurvivorRatio Eden和其中一個survivor的比值
-XX:PretenureSizeThreshold 大對象進入老年代的閾值,Serial和ParNew生效
-XX:MaxTenuringThreshold 晉升老年代的對象年齡,默認15, CMS默認是4
-XX:HandlePromotionFailure 老年代擔保
-XX:+UseAdaptiveSizePolicy動態調整Java堆中各個區域大小和進入老年代年齡
-XX:ParallelGCThreads 并行回收的線程數
-XX:MaxGCPauseMillis Parallel Scavenge參數,設置GC的最大停頓時間
-XX:GCTimeRatio  Parallel Scavenge參數,GC時間占總時間的比率,默認99%,即1%的GC時間
-XX:CMSInitiatingOccupancyFraction,old區觸發cms閾值,默認68%
-XX:+UseCMSCompactAtFullCollection(CMS完成后是否進行一次碎片整理,停頓時間加長)
-XX:CMSFullGCsBeforeCompaction(執行多少次不進行碎片整理的FullGC后進行一次帶壓縮的)
-XX:+ScavengeBeforeFullGC,在fullgc前觸發一次minorGC

垃圾回收統計信息
-XX:+PrintGC 輸出GC日志
-verbose:gc等同于上面那個
-XX:+PrintGCDetails 輸出GC的詳細日志

堆大小設置
-Xmx:最大堆大小
-Xms:初始堆大小(最小內存值)
-Xmn:年輕代大小
-XX:NewSize和-XX:MaxNewSize 新生代大小
-XX:SurvivorRatio:3 意思是年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區占整個年輕代的1/5
-XX:NewRatio=4:設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
-Xss棧容量 默認256k
-XX:PermSize永久代初始值
-XX:MaxPermSize 永久代最大值

生產環境參數配置(CMS-GC)

Java < 8
    -server
    -Xms<heap size>[g|m|k] -Xmx<heap size>[g|m|k]
    -XX:PermSize=<perm gen size>[g|m|k] -XX:MaxPermSize=<perm gen size>[g|m|k]
    -Xmn<young size>[g|m|k]
    -XX:+DisableExplicitGC
    -XX:SurvivorRatio=<ratio>
    -XX:+UseConcMarkSweepGC 
    -XX:+CMSParallelRemarkEnabled
    -XX:+CMSScavengeBeforeRemark
    -XX:+UseCMSInitiatingOccupancyOnly 
    -XX:CMSInitiatingOccupancyFraction=<percent>
    -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:"<path to log>"
    -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M
    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path to dump>`date`.hprof
    -Dsun.net.inetaddr.ttl=<TTL in seconds>
    -Djava.rmi.server.hostname=<external IP>
    -Dcom.sun.management.jmxremote.port=<port> 
    -Dcom.sun.management.jmxremote.authenticate=false 
    -Dcom.sun.management.jmxremote.ssl=false

Java >= 8
    -server
    -Xms<heap size>[g|m|k] -Xmx<heap size>[g|m|k]
    -XX:MaxMetaspaceSize=<metaspace size>[g|m|k]
    -Xmn<young size>[g|m|k]
    -XX:+DisableExplicitGC
    -XX:SurvivorRatio=<ratio>
    -XX:+UseConcMarkSweepGC 
    -XX:+CMSParallelRemarkEnabled
    -XX:+CMSScavengeBeforeRemark
    -XX:+UseCMSInitiatingOccupancyOnly
    -XX:CMSInitiatingOccupancyFraction=<percent>
    -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:"<path to log>"
    -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M
    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path to dump>`date`.hprof
    -Dsun.net.inetaddr.ttl=<TTL in seconds>
    -Djava.rmi.server.hostname=<external IP>
    -Dcom.sun.management.jmxremote.port=<port> 
    -Dcom.sun.management.jmxremote.authenticate=false 
    -Dcom.sun.management.jmxremote.ssl=false

理解GC日志

DefNew:Serial收集器新生代名稱 - Tenured - Perm
ParNew:ParNew收集器新生代名稱 - 
PSYoungGen:Parallel Scavenge收集器新生代名稱

JVM調優

  • GC的時間足夠的小

  • GC的次數足夠的少

  • 發生Full GC的周期足夠的長

前兩個目前是相悖的,要想GC時間小必須要一個更小的堆,要保證GC次數足夠少,必須保證一個更大的堆,我們只能取其平衡。

(1)針對JVM堆的設置,一般可以通過-Xms -Xmx限定其最小、最大值,為了防止垃圾收集器在最小、最大之間收縮堆而產生額外的時間,我們通常把最大、最小設置為相同的值

(2)年輕代和年老代將根據默認的比例(1:2)分配堆內存,可以通過調整二者之間的比率NewRadio來調整二者之間的大小,也可以針對回收代,比如年輕代,通過 -XX:newSize -XX:MaxNewSize來設置其絕對大小。同樣,為了防止年輕代的堆收縮,我們通常會把-XX:newSize -XX:MaxNewSize設置為同樣大小。-XX:PermSize,-XX:MaxPermSize設置為一樣防止老年代收縮。 -XX:NewRatio=4:設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5 -XX:MaxTenuringThreshold=0:設置垃圾最大年齡。如果設置為0的話,則年輕代對象不經過Survivor區,直接進入年老代。對于年老代比較多的應用,可以提高效率。如果將此值設置為一個較大值,則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。

(3)年輕代和年老代設置多大才算合理?這個我問題毫無疑問是沒有答案的,否則也就不會有調優。我們觀察一下二者大小變化有哪些影響 年輕代老年代設置:整個JVM內存大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦年輕代配置為整個堆的3/8。

  • 更大的年輕代必然導致更小的年老代,大的年輕代會延長普通GC的周期,但會增加每次GC的時間;小的年老代會導致更頻繁的Full GC

  • 更小的年輕代必然導致更大年老代,小的年輕代會導致普通GC很頻繁,但每次的GC時間會更短;大的年老代會減少Full GC的頻率

  • 如何選擇應該依賴應用程序對象生命周期的分布情況:如果應用存在大量的臨時對象,應該選擇更大的年輕代;如果存在相對較多的持久對象,年老代應該適當增大。但很多應用都沒有這樣明顯的特性,在抉擇時應該根據以下兩點:(A)本著Full GC盡量少的原則,讓年老代盡量緩存常用對象,JVM的默認比例1:2也是這個道理 (B)通過觀察應用一段時間,看其他在峰值時年老代會占多少內存,在不影響Full GC的前提下,根據實際情況加大年輕代,比如可以把比例控制在1:1。但應該給年老代至少預留1/3的增長空間

(4)在配置較好的機器上(比如多核、大內存),可以為年老代選擇并行收集算法: -XX:+UseParallelOldGC ,默認為Serial收集

(5)線程堆棧的設置:每個線程默認會開啟1M的堆棧,用于存放棧幀、調用參數、局部變量等,對大多數應用而言這個默認值太了,一般256K就足用。理論上,在內存不變的情況下,減少每個線程的堆棧,可以產生更多的線程,但這實際上還受限于操作系統。 -Xss256k:設置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。

(6)可以通過下面的參數打Heap Dump信息

  -XX:HeapDumpPath
  -XX:+PrintGCDetails
  -XX:+PrintGCTimeStamps
  -Xloggc:/usr/aaa/dump/heap_trace.txt
  通過下面參數可以控制OutOfMemoryError時打印堆的信息
  -XX:+HeapDumpOnOutOfMemoryError

注:通過分析dump文件可以發現,每個1小時都會發生一次Full GC,經過多方求證,只要在JVM中開啟了JMX服務,JMX將會1小時執行一次Full GC以清除引用.

性能分析工具

jps

-m 主類的參數 
-l 主類的全名,如果執行的是jar包,輸出jar路徑
-v 虛擬機參數

jstat

監視虛擬機運行狀態信息,包括類裝載、GC、運行期編譯(JIT)
用于輸出java程序內存使用情況,包括新生代、老年代、元數據區容量、垃圾回收情況
 jstat -gcutil 52670 2000 5 進程號 2s輸出一次一共5次

S0:幸存1區當前使用比例
S1:幸存2區當前使用比例
E:伊甸園區使用比例
O:老年代使用比例
M:元數據區使用比例
CCS:壓縮使用比例
YGC:年輕代垃圾回收次數
YGCT:年輕代垃圾回收消耗時間
FGC:老年代垃圾回收次數
FGCT:老年代垃圾回收消耗時間
GCT:垃圾回收消耗總時間

jmap

jmap:用于生成堆轉儲快照。一般稱為dump或heapdump文件。
jmap -histo 3618
上述命令打印出進程ID為3618的內存情況,包括有哪些對象,對象的數量。但我們常用的方式是將指定進程的內存heap輸出到外              部文件,再由專門的heap分析工具進行分析,例如mat(Memory Analysis Tool),所以我們常用的命令是:
jmap -dump:live,format=b,file=heap.hprof 3618
-F 強制生成dump快照

jstack

jstack:用戶輸出虛擬機當前時刻的線程快照,常用于定位因為某些線程問題造成的故障或性能問題。一般稱為threaddump文件。
參數
-F當正常輸出沒有響應的時候強制打印棧信息,一般情況不需要使用
-l長列表. 打印關于鎖的附加信息,一般情況不需要使用
-m 如果調用本地方法的話,可打印c/c++的堆棧

jinfo

查看和修改虛擬機參數

可視化工具 JConsole Java監視與管理控制臺 VisualVM 多合一故障處理工具

Java Class文件類型前綴

Element Type        Encoding
boolean             Z
byte                B
char                C
double              D
float               F
int                 I
long                J
short               S 
class or interface  Lclassname;
[L代表了相應類型數組嵌套的層數

內存泄漏及解決方法

1.系統崩潰前的一些現象:

每次垃圾回收的時間越來越長,由之前的10ms延長到50ms左右,FullGC的時間也有之前的0.5s延長到4、5s

FullGC的次數越來越多,最頻繁時隔不到1分鐘就進行一次FullGC

年老代的內存越來越大并且每次FullGC后年老代沒有內存被釋放

之后系統會無法響應新的請求,逐漸到達OutOfMemoryError的臨界值。

2.生成堆的dump文件 通過JMX的MBean生成當前的Heap信息,大小為一個3G(整個堆的大小)的hprof文件,如果沒有啟動JMX可以通過Java的jmap命令來生成該文件。

3.分析dump文件

下面要考慮的是如何打開這個3G的堆信息文件,顯然一般的Window系統沒有這么大的內存,必須借助高配置的Linux。當然我們可以借助X-Window把Linux上的圖形導入到Window。我們考慮用下面幾種工具打開該文件:

1.Visual VM 2.IBM HeapAnalyzer 3.JDK 自帶的Hprof工具

使用這些工具時為了確保加載速度,建議設置最大內存為6G。使用后發現,這些工具都無法直觀地觀察到內存泄漏,Visual VM雖能觀察到對象大小,但看不到調用堆棧;HeapAnalyzer雖然能看到調用堆棧,卻無法正確打開一個3G的文件。因此,我們又選用了Eclipse專門的靜態內存分析工具:Mat。

4.分析內存泄漏

通過Mat我們能清楚地看到,哪些對象被懷疑為內存泄漏,哪些對象占的空間最大及對象的調用關系。針對本案,在ThreadLocal中有很多的JbpmContext實例,經過調查是JBPM的Context沒有關閉所致。

另,通過Mat或JMX我們還可以分析線程狀態,可以觀察到線程被阻塞在哪個對象上,從而判斷系統的瓶頸。

5.回歸問題

Q:為什么崩潰前垃圾回收的時間越來越長?

A:根據內存模型和垃圾回收算法,垃圾回收分兩部分:內存標記、清除(復制),標記部分只要內存大小固定,時間是不變的,變的是復制部分,因為每次垃圾回收都有一些回收不掉的內存,所以增加了復制量,導致時間延長。所以,垃圾回收的時間也可以作為判斷內存泄漏的依據

Q:為什么Full GC的次數越來越多?

A:因此內存的積累,逐漸耗盡了年老代的內存,導致新對象分配沒有更多的空間,從而導致頻繁的垃圾回收

Q:為什么年老代占用的內存越來越大?

A:因為年輕代的內存無法被回收,越來越多地被Copy到年老代

調優方法

一切都是為了這一步,調優,在調優之前,我們需要記住下面的原則:

1、多數的Java應用不需要在服務器上進行GC優化;

2、多數導致GC問題的Java應用,都不是因為我們參數設置錯誤,而是代碼問題;

3、在應用上線之前,先考慮將機器的JVM參數設置到最優(最適合)

4、減少創建對象的數量;

5、減少使用全局變量和大對象;

6、GC優化是到最后不得已才采用的手段;

7、在實際使用中,分析GC情況優化代碼比優化GC參數要多得多;

GC優化的目的有兩個

1、將轉移到老年代的對象數量降低到最小;

2、減少full GC的執行時間;

為了達到上面的目的,一般地,你需要做的事情有:

1、減少使用全局變量和大對象;

2、調整新生代的大小到最合適;

3、設置老年代的大小為最合適;

4、選擇合適的GC收集器

感謝各位的閱讀,以上就是“Java垃圾收集器的介紹以及JVM調優方法”的內容了,經過本文的學習后,相信大家對Java垃圾收集器的介紹以及JVM調優方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

北流市| 芒康县| 马山县| 通海县| 张家界市| 蒙城县| 金平| 汶川县| 清流县| 扎囊县| 古交市| 杭州市| 翁源县| 西充县| 湟中县| 达尔| 乌恰县| 彰化市| 阿克苏市| 温泉县| 白水县| 呈贡县| 内乡县| 宁国市| 军事| 聊城市| 顺昌县| 法库县| 灵丘县| 壶关县| 墨竹工卡县| 方城县| 台中县| 麟游县| 延吉市| 久治县| 呼玛县| 恩施市| 乌鲁木齐市| 青神县| 天水市|