45.JVM调优策略、常见问题:内存泄漏(年老代堆空间被占满、持久代被占满、堆栈溢出、线程堆栈满、系统内存被占满)优化方法:优化目标、优化GC步骤、优化总结;案例分析(公司系统参数、网上给的配置参数)
45.JVM調優策略
45.1.常見問題
45.1.1.內存泄漏
45.1.1.1.年老代堆空間被占滿
45.1.1.2.持久代被占滿
45.1.1.3.堆棧溢出
45.1.1.4.線程堆棧滿
45.1.1.5.系統內存被占滿
45.2.優化方法
45.2.1.優化目標
45.2.2.優化GC步驟
45.2.3.優化總結
45.3.案例分析
45.3.1.案例1 Intellij IDEA 2016優化
45.3.2.公司系統參數
45.3.3.網上給的配置參數
45.3.4.Intellij IDEA 2016 默認參數
45.3.5.Intellij IDEA 2016
45.3.6.總結
45.JVM調優策略。
45.1.常見問題
45.1.1.內存泄漏
內存泄漏一般可以理解為系統資源(各方面的資源,堆、棧、線程等)在錯誤使用的情況下,導致使用完畢的資源無法回收(或沒有回收),從而導致新的資源分配請求無法完成,引起系統錯誤。整個JVM內存大小=年輕代大小 + 年老代大小 + 持久代大小,目前來說,常遇到的泄漏問題如下:
45.1.1.1.年老代堆空間被占滿
年老代堆空間被占滿 異常: java.lang.OutOfMemoryError: Java heap space這是最典型的內存泄漏方式,簡單說就是所有堆空間都被無法回收的垃圾對象占滿,虛擬機無法再在分配新空間。這種情況一般來說是因為內存泄漏或者內存不足造成的。某些情況因為長期的無法釋放對象,運行時間長了以后導致對象數量增多,從而導致的內存泄漏。另外一種就是因為系統的原因,大并發加上大對象,Survivor Space區域內存不夠,大量的對象進入到了老年代,然而老年代的內存也不足時,從而產生了Full GC,但是這個時候Full GC也無發回收。這個時候就會產生java.lang.OutOfMemoryError: Java heap space
解決方案如下:
1.代碼內的內存泄漏可以通過一些分析工具進行分析,然后找出泄漏點進行改善。
2.第二種原因導致的OutOfMemoryError可以通過,優化代碼和增加Survivor Space等方式去優化。
45.1.1.2.持久代被占滿
持久代被占滿 異常:java.lang.OutOfMemoryError: PermGen spacePerm空間被占滿。無法為新的class分配存儲空間而引發的異常。這個異常以前是沒有的,但是在Java反射大量使用的今天這個異常比較常見了。主要原因就是大量動態反射生成的類不斷被加載,最終導致Perm區被占滿。 解決方案:
1.增加持久代的空間 -XX:MaxPermSize=100M。
2.如果有自定義類加載的需要排查下自己的代碼問題。
45.1.1.3.堆棧溢出
堆棧溢出
異常:java.lang.StackOverflowError
一般就是遞歸沒返回,或者循環調用造成
45.1.1.4.線程堆棧滿
線程堆棧滿 異常:Fatal: Stack size too smalljava中一個線程的空間大小是有限制的。JDK5.0以后這個值是1M。與這個線程相關的數據將會保存在其中。但是當線程空間滿了以后,將會出現上面異常。 解決:增加線程棧大小。-Xss2m。但這個配置無法解決根本問題,還要看代碼部分是否有造成泄漏的部分。
45.1.1.5.系統內存被占滿
系統內存被占滿 異常:java.lang.OutOfMemoryError: unable to create new native thread這個異常是由于操作系統沒有足夠的資源來產生這個線程造成的。系統創建線程時,除了要在Java堆中分配內存外,操作系統本身也需要分配資源來創建線程。因此,當線程數量大到一定程度以后,堆中或許還有空間,但是操作系統分配不出資源來了,就出現這個異常了。 分配給Java虛擬機的內存愈多,系統剩余的資源就越少,因此,當系統內存固定時,分配給Java虛擬機的內存越多,那么,系統總共能夠產生的線程也就越少,兩者成反比的關系。同時,可以通過修改-Xss來減少分配給單個線程的空間,也可以增加系統總共內生產的線程數。
解決:
45.2.優化方法
45.2.1.優化目標
優化jvm其實是為了滿足高吞吐,低延遲需求來優化GC,之前遇到的情況中,其實不優化GC也是可以正常于行的,只不過偶爾會因為高并發給壓垮,但是也可以通過其他方式來解決這個問題。
45.2.2.優化GC步驟
1.首先需要觀察目前垃圾回收的情況,分析出老年代和年輕代回收的情況,適當的去調整內存大小和-XX:SurvivorRatio的比例。
2.根據垃圾收集器的特性,選擇適合自己業務的垃圾收集器,一般來說現在的WEB服務都是CMS+ParNew收集器。根據CMS收集器一般來說就會產生大量碎片,根據自己的需求選擇相應的壓縮頻率即可。
3.不斷的調整jvm內存比例,老年代、年輕代、以及持久代的比例,直到測試出一個比較滿意的值。
45.2.3.優化總結
總的來說GC優化不僅僅是加大內存可以解決的。需要綜合下業務特征和GC的時間,減少新生代大小可以縮短新生代GC停頓時間,因為這樣被復制到survivor區域或者被提升的數據更少,但是這樣一來yangGC的頻率就會很高,而且會有更多的垃圾進入到了老年代。如果增加新生代大小又會導致回收的時間和復制的時間變高,所以一般來說需要在這個中間進行折中。
像是針對大部分數據都在Eden區域被回收,并且幾乎沒有對象在survivor區域死亡的場景,完全可以減少-XX:MaxTenuringThreshold這個參數,讓數據提早進入Old,減少survivor區域的復制,來提高效率。
45.3.案例分析
45.3.1.案例1 Intellij IDEA 2016優化
45.3.2.公司系統參數
-server -Xms2g -Xmx2g -Xmn768m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=60 -XX:CMSTriggerRatio=70 -Xloggc:/data/bpm.coffee.session/logs/gc_20160704_110306.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/bpm.coffee.session/tmp/heapdump_20160704_110306.hprof45.3.3.網上給的配置參數
-server -Xms6000M -Xmx6000M -Xmn500M -XX:PermSize=500M -XX:MaxPermSize=500M -XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0 -Xnoclassgc -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:-CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=90 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log45.3.4.Intellij IDEA 2016 默認參數
-Xms158m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=240m -XX:+UseCompressedOops45.3.5.Intellij IDEA 2016
情景分析:
1.-Xms2g -Xmx2g 這兩個主要是設置初始堆大小和最大堆的大小,對比目前公司系統,網上參數和Intellij IDEA默認參數,總的來說在于場景問題,-Xms初始堆針對于服務器端的來說一般會設置跟最大堆一樣大,為什么呢?因為對于服務器來說啟動時間并不是最重要的,如果不夠了再去申請,這個對于大并發的場景來說是不合適的。而針對于客戶端Intellij IDEA來說,重點是啟動時間,所以初始堆設置比較小,這樣啟動的時間比較快。
2.-server 這個參數主要是用來指定運行模式的,指定了-server那么啟動的速度就會慢一些,所以針對于IDEA這種編輯器來說一般都使用默認的client模式
3.-XX:+UseCompressedOops 使用compressed pointers。這個參數默認在64bit的環境下默認啟動,但是如果JVM的內存達到32G后,這個參數就會默認為不啟動,因為32G內存后,壓縮就沒有多大必要了,要管理那么大的內存指針也需要很大的寬度了
4.-XX:ReservedCodeCacheSize=240m 這個主要是用來編譯代碼的,針對server來說用處不是很大.
5.針對于服務端來說-XX:+UseConcMarkSweepGC 老年代基本都是使用cms收集器,而年輕代都是使用-XX:+UseParNewGC進行收集的。
6.-XX:CMSInitiatingOccupancyFraction=60 這個參數主要是告訴cms收集器,內存到60%的時候進行回收,這個比例主要還是針對系統業務來決定的,太低容易內存溢出,太高容易內存浪費,而且老年代垃圾回收頻率高。一般來說都是在70到90之間,60過低了。
7.-Xloggc 這個參數一般都會打開,能夠很好的排查jvm的內存溢出.
8.-Xnoclassgc 這個針對一般業務來說都會打開,不讓class進行gc.
9.-XX:+DisableExplicitGC web業務來說,由于大家開發水平不一致,難保有人會使用System.gc(),高并發的場景這個肯定會是一個很大的影響,所以一般都關掉
10.-XX+UseCMSCompactAtFullCollection消除cms碎片
11.-XX:CMSFullGCsBeforeCompaction 這個上面填的0,如果沒有特殊場景,最好設置成1或者2.
12.-XX:-CMSParallelRemarkEnabled 主要用來降低cms標記的停頓,但是這個參數會增加碎片化,
13.SoftRefLRUPolicyMSPerMB 這個參數指定了軟飲用停留的時間,一般來說設置為0就好了,感覺生產中這個參數影響并不大,如果是針對單機內存使用緩存比較多的場景,這個值可以設置到1s左右,增加加吞吐量。
45.3.6.總結
jvm的調優需要根據自己的業務場景進行調整,沒有萬能的參數,但是總的來說,在生產環境中都會打開這幾個必須的參數
verbose: gc Xloggc:<pathtofile> XX:+PrintGCDetails XX:+PrintTenuringDistribution總結
以上是生活随笔為你收集整理的45.JVM调优策略、常见问题:内存泄漏(年老代堆空间被占满、持久代被占满、堆栈溢出、线程堆栈满、系统内存被占满)优化方法:优化目标、优化GC步骤、优化总结;案例分析(公司系统参数、网上给的配置参数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日喀则绿洲云邸是哪个开发商?
- 下一篇: 46栈内存溢出、内存区域(程序计数器、J