1、JITjava
java同時具備解釋型語言的跨平臺性,又有編譯型語言的本地性能
兩次編譯:第一次被編譯成java字節碼,JVM能夠直接解釋執行Java字節碼,也能夠用JIT先編譯成本地二進制彙編語言,再執行算法
-client:運行開始時就編譯
-server:運行後編譯,能夠更好地進行優化
-XX:TieredCompilation 分層編譯,先client-再server java8默認開啓 java8以前分層編譯有BUG
在64位JVM使用-client,JVM仍會使用-d64
而在32位JVM使用-d64, 會報錯緩存
代碼緩存:JIT編譯後的二進制代碼的緩存,當緩存滿時,新的代碼只能解釋執行
滿時警告:CadeCache is full
調整大小:-XX:ReservedCodeCacheSize=N java7默認96M
其餘:編譯閾值等用默認多線程
當方法或循環達到編譯閾值時,就會進入編譯隊列,異步進行代碼編譯,此時代碼仍可解釋執行;當下次調用方法或者循環進入下一輪時,會調用編譯後的代碼。併發
內聯:熱點的getter, setter在編譯時會被直接改爲p.name對對象變量的引用
默認開啓異步
逃逸優化:對於不存在線程共享的同步代碼,會去掉synchronized性能
逆優化:丟棄編譯後的二進制代碼
先前優化的代碼失效時:對象已經改變
分層編譯:client——server切換
殭屍代碼:長時間沒有使用的代碼會被丟棄優化
2、GC命令行
GC調優主要是減小GC的stop-the-world時間
1、內存劃分
young=eden+survivor
1.Eden滿後執行Minor GC, 存活的對象被堆積在同一Survivor
2.當一個Survivor滿後,其中存活的對象所有進入另外一個Survivor,同時對象年齡+1,
此過程當中,年齡達到MaxTenuringThreshold (最大/佔據/門檻)的對象進入Old
-->必有一個Survivor是空的
一些較大的對象,須要直接分配一塊較大的連續內存空間,則直接進入到老年代線程
old
Full GC - Major GC 時間是Minor GC 10倍以上
老年代對新生代對象的引用:
老年代中存在一個cardtable,全部老年代對象指向新生代對象的引用都會被記錄在這個表中。
當新生代執行GC的時候,只須要查詢card table來決定是否能夠被回收,而不用查詢整個old
permanent - 持久代又稱方法區
保存常量、字符串常量、class對象
class對象被回收的條件十分嚴苛:
1 全部實例被回收
2 加載該類的ClassLoader被回收
3 Class對象沒法經過任何途徑訪問(包括反射)
java8中將永久代變爲了元空間:
元空間只保存對JIT和JVM運行有關的數據,Class,反射對象等被轉移到普通堆空間了
元空間可使用的內存是無限的,不須要參數調整
2、GC算法
一、根搜索算法 - 從root引用不到的對象,爲不可達對象,將被GC
能夠做爲Root的對象有:
虛擬機棧中引用的對象-本地變量表
本地方法棧中引用的對象-Native方法
方法區靜態屬性引用的對象
方法區常量引用的對象
二、標記-清除算法 - 先掃描全部對象,標記全部存活,再清除全部未被標記的對象
在存活對象不少時適合,由於不用移動存活對象
不會移動對象,高效但會致使內存碎片
三、複製算法 - 將內存分爲兩個區,每次只使用一個區
在存活對象不多時適合,由於要移動全部存活對象
50%的內存浪費
四、標記-整理算法 - 比2多了一步整理
Major GC通常使用標記-整理算法
Minor GC通常使用複製算法
3、回收器 - 每一個回收器都存在stop-the-world問題
一、Serial (-XX:+UseSerialGC) 用於年輕代
使用:複製算法
二、SerialOld (-XX:+UseSerialGC) 用於老年代
使用:標記-整理算法
*三、ParNew (-XX:+UseParNewGC) 用於年輕代
使用:複製算法
Serial的多線程版本
*四、ParallelOld(-XX:+UseParallelOldGC) 用於老年代
使用:標記-整理算法
Serial的多線程版本
吞吐量優先
五、ParrallelScavenge (-XX:+UseParallelGC) 用於年輕代
使用:複製算法
可控吞吐量(吞吐量=用戶代碼執行時間/用戶代碼執行時間+GC時間
*六、CMS (-XX:+UseConcMarkSweepGC) 用於老年代
*使用:標記-清理算法
初始標記(STW) - 併發標記 - 併發預清理 - 從新標記(STW) - 併發清理 - 併發重置
初始標記:STW-找到和根對象直接關聯的對象
併發標記:找到和初始標記對象關聯的對象
併發預處理:找到在併發標記階段晉升的對象,減小下一階段從新標記的工做量
從新標記:STW-從新從根對象開始查找並標記併發階段遺漏的對象
併發清理:--
併發重置:重置CMS狀態
缺點:
內存碎片
GC線程和應用線程併發執行,消耗更多CPU資源,吞吐量低(存在線程切換)
內存浪費-默認68%就出發GC XX:CMSinitiatingOccupandcyFraction=n
若是CMS後臺線程沒法得到完成GC的CPU資源,或者內存碎片嚴重沒法找到連續空間分配內存,
CMS會蛻化成Serial收集器,進行一次Serial收集。以後又變回CMS收集
七、G1收集器 - 用於老年代和年輕代,是商用收費的收集器
適合處理超大堆
將堆劃分爲若干個區域Region
老年代也被劃分爲多個Region,採用複製算法
參數調整
1.堆大小
-Xms4096m
-Xmx4096m
2.代空間
-XX:NewRatio=N youngSize = heapSize / 1+N
-XX:NewSize=1024m -XX:MaxNewSize=1024m 顯示指定young代大小
永久代
-XX:PermSize=N -XX:MaxPermSize=N
元空間
不須要調整
3.收集器
吞吐量優先:
-XX:+UseParallelGC
-XX:+UseParallelOldGC
響應優先:
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
參數:
自動調整:
JVM運行過程當中,會根據以往的性能歷史,自動調整堆、代已經Survivor大小,
默認開啓,能夠用-XX:-UseAdaptiveSizePolicy關閉
若是將-Xms -Xmx設置成同樣的值,-XX:NewSize -XX:MaxNewSize設置成同樣的值,那麼自動調節功能將被關閉 -XX:ParallelGCThreads 會根據CPU核心數自動調整 日誌: -XX:+PrintGCDetails 打印詳細GC日誌 -XX:+PrintGCTimeStamps 打印GC日誌生成的時間 -Xloggc:filename 限定GC日誌路徑,默認是標準輸出(命令行)