JVM參數調優:Eclipse啓動實踐

JVM參數調優:Eclipse啓動實踐 html

本文主要參考自《深刻理解 Java 虛擬機》。 這本書是國人寫的可貴的不是照搬代碼註釋的且不是廢話連篇的技術書,內容涵蓋了 Java 從源碼到字節碼到執行的整個過程,包括了 JVM(Java Virtual Machine)的架構,垃圾收集的介紹等。這裏摘錄出關於配置 JVM 基本參數來調優 Eclipse 啓動的過程,比較初級,供初學者參考。 java

基礎知識

針對 JVM 的參數調優主要集中在數據區大小的控制和垃圾回收策略的選擇。關於 JVM 運行機制等更多內容可參考其餘博文 算法

JVM 的運行時數據區

運行時 JVM 的數據區主要包括各線程私有的棧和程序計數器,線程共享的方法區,以及管理對象的堆(又稱回收堆)等。程序運行時,類信息、常量、靜態變量等會被加載到方法區。運行過程當中幾乎全部對象都在堆裏,內存佔用的空間最大,這也是最值得優化得部分。 macos

JVM 的垃圾回收策略

Java 程序中,除了基本類型(primitive types),其餘的數據都是以對象的形式存在。對象生命週期有長有短,若是無區別的保留在內存中,會形成內存超載。內存垃圾回收(Garbage Collection, 縮寫 GC)就是解決這一問題的策略。 架構

注意:JVM 不只僅只對對象進行垃圾回收,實際上也會對廢棄常量和無用的類作回收。 oracle

垃圾回收首先得找到須要被回收的對象,通常採用根搜索算法來標記處這些過期的對象(另外有一種簡單的實現:引用計數,但存在明顯的弊端,即循環引用)。 app

回收垃圾的過程會消耗計算資源和時間。根據不一樣的處理方式,垃圾回收有不一樣的策略,如今經常使用的是分代收集算法:根據對象的存活週期將堆劃分爲幾代: 新生代(Young Generation 或 New Generation)和老生代(Tenured Generation),HotSpot 虛擬機裏還分出了永生代(基本等同於方法區)。不一樣代採用不一樣的垃圾回收策略。 eclipse

HotSpot 虛擬機

HotSpot 虛擬機中,Perm 代指永生代,Old 代指老年代,而新生代使用複製算法,將區域劃分爲三塊:Eden,S0 和 S1(S 是 Survivor 的縮寫)。 jvm

IBM 研究代表,新生代中的對象 98%是朝生夕死的,三者的比例劃分是 8:1:1。對象先分配到 Eden,若是 Eden 中內存佔用量達到必定得比例,觸發 Minor GC,JVM 會將 Eden 和 S0(或 S1)中存活的對象複製到 S1(或 S0),並清空 Eden 和 S0(或 S1)。若是同時老年代的內存佔用量打達到必定比例,會觸發 Major GC(也稱 Full GC)。一般 Major GC 比 Minor GC 慢 10 倍以上。 ide

編譯過程

Java 一直號稱「Write once, run anywhere」,這個特性正是由 JVM 這一虛擬層來支撐的。

Java 源代碼首先編譯爲 Java 字節碼,字節碼再被 JVM 加載運行。運行的過程能夠是直接針對字節碼的解釋執行,也能夠是通過了 JIT(Just in time)編譯爲機器碼後的執行。另外,還有靜態提早編譯器(Ahead Of Time,也縮寫爲 AOT),能將源碼直接編譯爲機器碼。

HotSpot 虛擬機的 JIT 編譯器有:Client Complier(簡稱 C1)、Server Complier(簡稱 C2)以及在 Java7 中堆出的分層編譯器。C1 編譯器作一些快速的優化,C2 作一些更耗時的優化可是產生更高效的代碼,而分層編譯器則結合了二者的優勢:快速的啓動和逐步的優化(brings client startup speeds to the server VM)。

性能監控和故障處理工具

對於系統調優和問題定位,周志明在《深刻 Java 虛擬機》中總結到

給一個系統定位問題的時候,知識、經驗是關鍵基礎,數據是依據,工具是運用知識處理數據的手段。這裏說的數據包括:運行日誌、異常堆棧、GC 日誌、線程快照、堆轉儲快照等……應當意識到工具永遠都是知識技能的一層包裝,沒有什麼工具是「祕密武器」。

Java 提供了不少工具給開發者來監控和處理運行中的問題。包括命令行工具以及可視化工具

命令行工具

好比 jps, jstat, jinfo 等。舉例以下:

1 2 3
jstat -gcutil xxx #xxx 是 jps 查出的 LVMID,查看 gc 相關數據 jstat -gccause xxx#查看 gc 的緣由 jinfo -flag XXX xxx#XXX 是參數名,xxx 是 VMID,查看虛擬機的參數值

可視化工具

  • JConsole:比較老得分析軟件,Java 自帶。Windows 下搜 jconsole.exe,Mac 下啓動命令爲 jconsole
  • Eclipse Memory Analyzer Tool:用於分析 dump 下的堆數據
  • VisualVM:推薦,很全能的分析工具

JVM 參數

這裏零散的羅列了一些我用到的簡單的 JVM 配置參數:

內存大小控制:

  • -Xmx20M: 堆的最大值
  • -Xms10M: 堆的初始分配內存
  • -Xmn: 新生代堆的分配內存
  • -Xss128k: 線程的棧空間大小
  • -XX:PermSize=10M | 方法區初始大小
  • -XX:MaxPermSize=10M |方法區最大值

編譯相關:

  • -Xint: 關閉 JIT,徹底使用解釋執行,實踐中沒什麼做用,解釋執行很慢。
  • -client: 啓動 C1 編譯器
  • -server: 啓動 C2 編譯器
  • -XX:+TieredCompilation: 啓動分層編譯器

其餘:

  • -XX:+DisableExplicitGC: 屏蔽 System.gc()調用
  • -PrintGCDetails: 讓 jvm 在每次發生 gc 的時候打印日誌,利於分析 gc 的緣由和情況
  • -XX:+HeapDumpOnOutOfMemoryError: 內存溢出時 dump 下 heap,能夠經過 Eclipse Memory Analyzer Tool 打開查看。
  • -XX:HeapDumpPath=/: dump 下的 heap 文件快照的路徑。Eclipse 中默認放到項目的根目錄中
  • -XVerify:none: 禁止字節碼驗證

調優 Eclipse 啓動的實踐

實踐環境

  • CPU: 2.8 GHz Intel Core i7
  • 內存: 8 GB 1333 MHz DDR3
  • 操做系統: OS X 10.9.1(64bits)
  • Eclipse:Version: Kepler Service Release 1, Build id: 20130919-0819
  • Java:java version 「1.7.0_45」

調優實踐

調優 Eclipse 啓動實際上就是調優 Eclipse 在 JVM 中的加載和程序啓動階段的運行。因爲默認的 Ecpise 啓動配置沒法適應全部不一樣的硬件、軟件環境,作針對性的調優是必要的。

Eclipse 的啓動配置文件是 eclipse.ini,對 JVM 的參數調優直接在該文件中修改。OS X 下,其文件路徑爲 $ECLIPSE/Eclipse.app/Contents/MacOS/eclipse.ini(注意不是 Eclipse 文件包根目錄下得 eclipse.ini)。

測 Eclipse 啓動時間

要優化 Eclipse 的啓動時間,先要能肯定 Eclipse 的啓動時間。這裏推薦網友實現的一個 Eclipse 插件:計算啓動時間的 Eclipse 插件。下載後放到 Eclipse 的插件包中,啓動 Eclipse 便可看到彈窗顯示的啓動時間。爲了獲得一個儘量公平的測試結果,須要在測試過程當中關閉其餘程序,避免 CPU 負載帶來的偏差,並屢次測試取平均值。

調優策略

使用 VisualVM 查看程序的運行情況來定位瓶頸,嘗試調優解決。下圖是 VisualVM 的示例圖,右邊圖示展現了 GC 的狀態以及編譯時間、類加載時間和垃圾回收時間等指標。

img

也能夠經過命令行工具查看 GC 的狀態,好比:jstat -gc XXX #其中 XXX 是 jps 查出的進程的 LVMID.

個人實踐總結以下:

  • 類加載時間過長:禁止加載類時的字節碼驗證。咱們認爲 Eclipse 的字節碼是可靠的。-XVerify:none
  • 編譯時間:-client縮短了編譯時間,但長期運行的性能可能受影響,-server編譯時間長,而編譯優化作得更多,後期使用匯報大,-XX:+TieredCompilation分層編譯則集合了前二者的優點。沒有特殊需求,可選用這一編譯選項。
  • Minor GC 次數太多:新生代空間過小,加大新生代的內存大小。-Xmn800m,同時,增大回收堆的總大小上限(-Xmx1024m)。
  • Full GC 次數太多:爲了不回收堆由小到大的動態增加增長時間開銷,可將其初始大小跟最大上限設定爲同一值-Xms1024m,並增長老年代的大小(-XX:PermSize=256m,-XX:MaxPermSize=256m)。
  • 代碼中的 GC 調用:Eclipse 代碼中有 System.GC()的調用可能促使 JVM 執行垃圾回收,能夠經過-XX:+DisableExplicitGC來防止。
  • 垃圾收集器的選擇:垃圾收集器有不少,好比 Serial、ParNew、Parallel Scavenge、CMS、G1 等。推薦使用老生代 CMS 新生代 ParNew 的組合來應對 Eclipse 用戶交互頻繁的狀況(-XX:+UseParNewGC、-XX:+UserConcMarkSweepGC)。同時提高 CMS 的垃圾回收的觸發條件:-XX:CMSInitiatingOccupancyFraction=85,進一步下降 Full GC 的出現。

最終 eclipse.ini

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
-startup ../../../plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar --launcher.library ../../../plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.200.v20130807-1835 -product org.eclipse.epp.package.standard.product --launcher.defaultAction openFile -showsplash org.eclipse.platform --launcher.XXMaxPermSize 256m --launcher.defaultAction openFile --launcher.appendVmargs -vmargs -Dosgi.requiredJavaVersion=1.6 -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts -Xms1024m -Xmx1024m -Xmn800m -Xdock:icon=../Resources/Eclipse.icns -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts -XX:+TieredCompilation -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC -XVerify:none -XX:+UseParNewGC -XX:+UserConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85

其餘參考

 原文地址: http://biaobiaoqi.me/blog/2014/01/17/java-performance-tunning-in-practice/
相關文章
相關標籤/搜索