目錄
常見配置
其一是標準參數(-),所有的JVM實現都必須實現這些參數的功能,而且向後兼容;
其二是非標準參數(-X),默認jvm實現這些參數的功能,但是並不保證所有jvm實現都滿足,且不保證向後兼容;
其三是非Stable參數(-XX),此類參數各個jvm實現會有所不同,將來可能會隨時取消,需要慎重使用;
-client //client模式,啓動速度比較快運行時性能和內存管理效率不高,通常用於客戶端應用程序或者開發和調試。
-server //server模式,啓動速度比較慢,但運行時性能和內存管理效率很高,適用於生產環境
-jar //以jar包的形式執行一個應用程序。
//jar包的manifest文件中聲明初始加載的Main-class,Main-class必須有public static void main(String[] args)方法
-D<property>=<value> //系統級全局變量值,系統屬性名/值對 如-Dname="space string"
-classpath 路徑 或-cp 路徑 //使用-classpath後jvm將不再使用CLASSPATH中的類搜索路徑
java調優一般針對 堆內存
堆=年輕代+老年代+持久代
堆設置
-Xms //初始堆大小
-Xmx //最大堆大小
-Xmn //年輕代大小,NewSize與MaxNewSize設爲一致
-XX:NewSize=n //年輕代初始大小
-XX:MaxNewSize=n // 年輕代最大大小
-XX:NewRatio=n //設置年輕代和年老代的比值。如:爲3,表示年輕代與年老代比值爲1:3,年輕代佔整個年輕代年老代和的1/4
-XX:SurvivorRatio=n //年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區佔整個年輕代的1/5
-XX:PermSize //設置持久代初始值
-XX:MaxPermSize=n //設置持久代最大值
收集器設置
-XX:+UseSerialGC :設置串行收集器
-XX:+UseParallelGC :設置並行收集器
-XX:+UseParalledlOldGC :設置並行年老代收集器
-XX:+UseConcMarkSweepGC :設置併發收集器
並行收集器設置
-XX:+UseParNewGC //設置年輕代爲並行收集
-XX:ParallelGCThreads=n //設置並行收集器的線程數
-XX:MaxGCPauseMillis=n //設置並行收集最大暫停時間
-XX:GCTimeRatio=n //設置垃圾回收時間佔程序運行時間的百分比。公式爲1/(1+n)
-XX:+UseAdaptiveSizePolicy //自動選擇年輕代區大小和相應的Survivor區比例
併發收集器設置
-XX:+CMSIncrementalMode //設置爲增量模式。適用於單CPU情況。
-XX:ParallelGCThreads=n //設置併發收集器年輕代收集方式爲並行收集時,使用的CPU數。並行收集線程數。
CMS收集器(老年代 – 併發GC)
-XX:CMSFullGCsBeforeCompaction=n //多少次後進行內存壓縮
-XX:+CMSParallelRemarkEnabled //降低標記停頓
-XX:CMSInitiatingOccupancyFraction=n //使用n%剩餘堆時開始CMS收集
垃圾回收統計信息
-XX:+PrintGC //打印GC
-verbose:gc //同-XX:+PrintGC
-XX:+PrintGCDetails //打印GC詳細信息
-XX:+PrintGCTimeStamps //打印CG時間戳(以基準時間的形式)
-XX:+PrintGCDateStamps //打印GC時間戳(以日期的形式)
-Xloggc:<filename> //指定GC log的位置,以文件輸出
內存溢出時自動產生dump
-XX:+DisableExplicitGC //禁止代碼中調用GC,System.gc()會變成一個空調用
-XX:+HeapDumpOnOutOfMemoryError //JVM在出現內存溢出時自動Dump出當前的內存轉儲快照
-XX:HeapDumpPath=${目錄} //生成DUMP文件的路徑
-Djava.awt.headless=true
回收機制
年輕代(Young Generation) 年老代(Old Generation) 持久代(Permanent Generation)
年輕代包括(一個Eden區,兩個Survivor區:對稱沒先後關係一個稱爲(From sqace),一個稱爲(To Space)。)
- 每次使用Eden和其中一塊Survivor
- 大部分對象在Eden區中生成,
- Eden內存不夠,就進行Minor GC
- 每次回收時,將Eden和Survivor中還存活着的對象一次性複製到另外一塊Survivor空間
- 重複多次(默認15次,最多15次):對象晉身, Survivor中沒有被清理的對象就會複製到老年區(Old)
- Survivor對象大於50%也會對象晉身, 複製到老年區(Old)
年老代 在年輕代中經歷了N次垃圾回收後仍然存活的對象,就會被放到年老代中。因此年老代中存放的都是一些生命週期較長的對象
持久代 存放靜態文件,如今Java類、方法等。持久代對垃圾回收沒有顯著影響
GC有兩種類型:Scavenge GC和Full GC。
Minor GC (Scavenge GC) //清理年輕代
新對象生成,並且在年輕代的Eden區申請空間失敗時,就會觸發Scavenge GC對Eden區域進行GC,清除非存活對象。不會影響到年老代
Major GC //清理老年代
Full GC //清理新生代,老年代區域,成本較高,會對系統性能產生影響。
對整個堆進行整理,比Scavenge GC要慢,因此應該儘可能減少Full GC的次數。在對JVM調優的過程中,很大一部分工作就是對於FullGC的調節。有如下原因可能導致Full GC:
· 年老代(Tenured)被寫滿
· 持久代(Perm)被寫滿
· System.gc()被顯示調用
· 上一次GC之後Heap的各域分配策略動態變化
Full GC會觸發 STW(stop the word) 程序停止工作
調優:,不讓出現Full GC
Jvm監控工具
獲取對應進程的線程運行情況, JDK自帶一些工具,如Jstack , jmap ,
top –Hp pid
jstack , 輸出的線程信息主要包括:jvm自身線程、用戶線程等。jvm線程會在jvm啓動時就會存在。對於用戶線程則是在用戶訪問時纔會生成。
jstack <pid>,用於打印指定Java進程的線程堆棧信息。
jstat –gc 進程號 時間(1000毫秒) 顯示gc的信息,查看gc的次數,及時間。其中最後五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間
jmap , 產生dump,打印Java進程的共享對象內存映射或堆內存細節, 各廠商的jvm 手工dump 方法有小區別,如Oracle JVM的6.0版本去掉了-XX:+HeapDumpOnCtrlBreak參數
jmap -histo <pid> 展示class的內存情況
jmap -histo:live <pid> 先觸發gc,然後再統計信息
jmap -dump:format=b,file=<filename> <pid> 手動產生dump文件, 將進程的內存heap輸出出到filename文件裏,
例: 統計25923 進程狀況
top -Hp 25923 >top.log
jstack 25923 >./jstack.info
jstat -gcoldcapacity -t 25923 250 3 >gcold.log
jstat –gc 25923 1000 >./gc.log
jmap -dump:format=b,file=dump.bin 25923
Dump文件是Java堆使用情況的內存鏡像。主要包括系統信息、虛擬機屬性、完整的線程Dump、所有類和對象的狀態等
懷疑有內存泄漏的時候就可以製作Dump來查看具體情況
每一個java虛擬機都有及時生成顯示所有線程在某一點狀態的線程dump的能力
內存dump文件格式:***.hprofdump,配合內存分析工具MAT或與jhat使用,能夠以圖像的形式直觀的展示當前內存是否有問題
JVM中的許多問題都可以使用線程dump文件來進行診斷,其中比較典型的包括線程阻塞,CPU使用率過高,JVM Crash,堆內存不足和類裝載等問題。
CPU爆滿原因分析:
- 大量IO
- 大量輪詢
- FULL GC清理不掉,一直卡在fullgc