JVM 調優總結

1、堆與棧java

一、堆是全部對象共享的,存儲對象信息;算法

每個線程都有一個獨立的線程棧,棧存儲的是與當前線程相關的信息,包括局部變量、程序運行狀態、方法返回值等。服務器


二、堆中存儲的是對象,棧中存儲的是基本類型堆中對象的引用多線程


三、棧的大小配置  -Xss併發


四、在運行棧中,基本類型和引用的處理是同樣的,都是傳值。spa


五、能夠把一個對象看做爲一棵樹,對象的屬性若是仍是對象,則仍是一棵樹(非葉子節點),而基本類型則是葉子節點。操作系統


2、Java對象的大小線程

一、一個空的Object對象:對象

Object obj = new Object();遞歸

其所佔的空間爲: 8+4 =12 bytes 。其中8 bytes 是Java堆中對象的所需空間,4 bytes是棧中保存引用的所需空間


二、如下類

class NewObject

{

    int count;

    boolean flag;

    Object obj;

}

其的對象  NewObject  newObj = new NewObject();

newObj 所佔空間 8 + 4 +1 + 4 = 17 bytes.

其中8 bytes 爲 newObj 空對象大小,4 bytes爲 int 大小,1 byte爲 boolean 大小, 4 bytes爲 obj引用大小。

又由於Java對象內存分配以8的整數倍來分,故而對象的大小爲 24 bytes。


三、基本類型包裝類的大小至少是16bytes。


3、強引用、軟引用、弱引用

強引用:回收時候嚴格判斷

軟引用:內存緊張則回收,富餘則不回收

弱引用:每次GC一定回收,生命週期只存在於一個垃圾回收週期。


4、GC 基本策略


一、引用計算:沒法處理循環引用


二、標記-清除:從root節點開始標記全部引用對象,遍歷堆,清除未標記對象。缺點是須要暫停整個應用,產生內存碎片。


三、複製:將內存分爲兩塊,每次只使用其中一塊。回收時候複製到另外一塊。


四、標記整理:結合 「標記-清除」  和 「複製」, 不過不是複製到另外一塊內存,而是將對象放緊湊。


5、GC 分區策略


一、增量收集:實時垃圾回收。


二、分代收集:把對象分爲年輕代、年老代、持久代,對於不一樣生命週期對象採用不一樣算法。


6、GC 線程策略


一、串行收集:單線程處理,沒法使用多處理器的優點。須要暫停整個運行環境。

優勢:簡單,效率高。

缺點:只適合小型應用,數據量比較小。

配置:-XX:+UseSerialGC


二、並行收集:多線程處理,速度快,效率高。須要暫停整個運行環境。

優勢:吞吐量大,適用於數值計算、後臺處理。

缺點:響應時間長。

配置:XX:+UseParallelGC   -XX:+UseParallelOldGC    -XX:ParallelGCThreads=<N>   -XX:MaxGCPauseMillis=<N>   -XX:GCTimeRatio=<N>


三、併發收集:GC的同時不須要暫停整個運行環境。

優勢:響應時間快,適用於Web服務器等。

缺點:吞吐量沒那麼大。

配置:-XX:+UseConcMarkSweepGC  -XX:CMSInitiatingOccupancyFraction=<N>


7、分代回收


一、年輕代(Yong):一個Eden區,兩個Survivor區。Eden滿,放入一個Survivor。Survivor放入另外一個Survivor。另外一個Survivor滿,放入年老代。


二、年老代(Tenured):年輕代經歷N次GC後,對象放到年老區。放的是生命週期較長的數據。


三、持久代(Permanent):Java 類的 Class 信息,與GC關係不大。


Minor GC:只要Eden滿即觸發,速度很快。

Full GC:整個堆回收,速度慢。在年老代或者持久代滿的時候調用。


8、典型配置

java -Xmx3550m -Xms3550m -Xmn2g –Xss128k  -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0 XX:+UseConcMarkSweepGC -XX:+UseParNewGC  

-Xmx3550m: 最大可用內存

-Xms3550m:初始內存。此值能夠設置與-Xmx相同,以免每次垃圾回收完成後JVM從新分配內存。

-Xmn2g:年輕代大小

-Xss128k:每一個線程的棧大小

-XX:NewRatio=4: 年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)

-XX:SurvivorRatio=4:年輕代中Eden區與Survivor區的大小比值

-XX:MaxPermSize=16m: 持久代大小 

-XX:MaxTenuringThreshold=0: 垃圾最大年齡。若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代

-XX:+UseParallelGC:選擇並行收集器

-XX:ParallelGCThreads=20: 並行收集器的線程數

-XX:+UseParallelOldGC: 年老代垃圾收集方式爲並行收集

-XX:MaxGCPauseMillis=100:每次年輕代垃圾回收的最長時間

-XX:+UseAdaptiveSizePolicy:自動選擇年輕代區大小和相應的Survivor區比例

-XX:+UseConcMarkSweepGC:設置年老代爲併發收集

-XX:+UseParNewGC: 設置年輕代爲並行收集

-XX:CMSFullGCsBeforeCompaction=5:運行多少次GC之後對內存空間進行壓縮、整理。

-XX:+UseCMSCompactAtFullCollection:打開對年老代的壓縮


9、調優總結


一、吞吐量優先:

年輕代大並行垃圾收集、年老代小

儘量回收掉大部分短時間對象,減小中期的對象,而年老代盡存放長期存活對象。


二、響應時間優先:

年輕代大、併發垃圾回收、年老代適中。

年老代使用併發收集器,因此其大小須要當心設置,通常要考慮併發會話率和會話持續時間等一些參數。若是堆設置小了,能夠會形成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式;若是堆大了,則須要較長的收集時間


10、年老代碎片問題:

解決:

一、-XX:+UseCMSCompactAtFullCollection:使用併發收集器時,開啓對年老代的壓縮。

二、-XX:CMSFullGCsBeforeCompaction=0:上面配置開啓的狀況下,這裏設置多少次Full GC後,對年老代進行壓縮


11、常見JVM 異常

一、java.lang.OutOfMemoryError: Java heap space

緣由:典型的內存泄露,全部堆空間都被沒法回收的垃圾對象佔滿。

解決:找到泄露點,通常是集合對象引用。


二、java.lang.OutOfMemoryError: PermGen space

緣由:持久代佔滿,沒法爲新的class分配存儲空間而引起的異常。主要緣由是大量動態反射生成的類不斷被加載。不一樣的classloader 即使使用了相同的類,可是都會對其進行加載,至關於有一個class會被N個classloader加載N次。

解決:-XX:MaxPermSize=16m


三、java.lang.StackOverflowError

緣由:遞歸沒有返回,或者循環調用。

解決:修正代碼


四、Fatal: Stack size too small

緣由:線程空間大小被限制

解決:增大線程棧,-Xss2m。也多是代碼內存泄露。


五、java.lang.OutOfMemoryError: unable to create new native thread

緣由:操做系統沒有足夠資源產生這個線程

解決:配置系統,如ulimit。減少線程棧大小,-Xss。

相關文章
相關標籤/搜索