垂直打擊之JVM剖析

讓Java應用程序運行是一回事,但讓他們跑得快就是另外一回事了。在面對對象的環境中,性能問題就像來勢兇猛的野獸。但JVM的複雜性將性能調整的複雜程度增加了一個級別。這裡Refcard涵蓋了JVM internals、class loading(Java8中更新以映射最新的元空間)、垃圾回收、故障診斷、檢測、併發性,等等。

介紹

Java是目前軟件開發領域中使用最廣泛的編程語言之一。Java應用程序在許多垂直領域(銀行、電信、醫療保健等)中都有廣泛使用。Refcard的目的是,幫助開發者通過專注於JVM內部,性能調整原則和最佳實踐,以及利用現有監測和故障診斷工具,來提升應用程序在商業環境中的性能。

它能以不同的方式定義“optimal performance(最佳性能)”,但基本要素是:Java程序在業務響應時間要求內執行計算任務的能力,程序在高容量下執行業務功能的能力,並具有可靠性高和延遲低的特點。有時,數字本身變得模式化:對於一些大型網站,優秀的頁面響應時間應該在500ms以下。在適當的時候,Refcard包括目標數字。但在大多數情況下,您需要根據業務需求和現有的性能基準自己決定這些。

JVM Internals

基礎知識

垂直打擊之JVM剖析

代碼編譯和JIT

編譯Java字節碼顯然沒有直接從主機執行本機代碼那麼快。為了提高性能,Hotspot JVM找出最繁忙的字節碼區域,然後將其編譯成更高效地原生、機器代碼(自適應優化)。然後這種本地代碼就會存儲在非堆內存中的代碼緩存中。

注意:多數的JVM是通過禁用JIT編譯器實現的(Djava.compiler=NONE)。您只需要考慮禁用的關鍵性優化,比如JVM崩潰。

下圖說明了Java源代碼,即時編譯流程和生命週期。

垂直打擊之JVM剖析

內存空間

HotSpot Java Virtual Machine是由以下的存儲空間組成。

存儲空間描述Java HeapJava程序類實例和數組的主存儲器。Permanent Generation(JDK 1.7及以下版本)Metaspace (JDK 1.8及以上版本)Java類元數據的主存儲器。注意:從Java 8開始,PermGen空間就由元空間和使用本地存儲器替換了,類似於IBM J9 JVM。Native Heap(C-Heap)本地內存存儲線程、棧、包括對象的代碼緩存,如MMAP文件和第三方本機庫。

類加載

Java的另一個重要特點是,在JVM啟動之後,它能夠加載編譯的Java類(字節碼)。根據程序的大小,在剛剛重啟之後,程序在類加載過程中性能會顯著降低。這種現象是因為內部JIT編譯器在重啟之後需要重新開始優化。

自JDK 1.7版本之後,有一些改進值得大家重視。例如默認的JDK class loader具有更好的裝在類併發能力。

熱點

關注的區域建議JVM重啟後的性能下降避免部署過量的Java類到一個單一的應用程序類加載器(例如:非常大的WAR文件)運行時發現過多的類加載爭奪(thread lock, JAR file searches…) ,降低了整體性能。分析您的應用程序並識別代碼模塊進行動態類加載操作過於頻繁。積極尋找非一站式類加載錯誤,如ClassNotFoundException和NoClassDefFoundError。再訪Java映射API和適用情況下優化的過度使用。java.lang.OutOfMemoryError: PermGen space (JDK 1.7及以下版本)java.lang.OutOfMemoryError:元空間(JDK 1.8及以上版本)再訪JVM Permanent Generation、Metaspace (MaxMetaSpaceSize)和本地內存容量在適用情況下的尺寸。分析應用程序類加載器和識別元數據的內存洩漏的源頭。

垂直打擊之JVM剖析

故障診斷和監視

目標建議跟蹤那些加載到不同的類加載器的Java類。配置程序選擇使用的Java profiler,例如JProfiler或Java VisualVM。將重點放在類加載器的操作和內存佔用上。可以通過–verbose:class. for the IBM JVM,生成多個Java核心快照跟蹤活動的類加載器和加載類。調查類元數據的內存洩露的可以來源。配置程序和定義可能的culprit(s)。生成並分析JVmheap dump快照,專注於類加載器和java.lang.Class中的實例。

垂直打擊之JVM剖析

確保適當的Permanent Generation / Metaspace和本地內存大小。密切監視你的PermGen、元空間和本機內存利用率,並調整到適合的最大容量。分析程序類加載器的大小,並尋找機會適當地減少元數據足跡。

垃圾回收

Java垃圾回收流程對於程序性能是至關重要的。為了提供有效的垃圾回收,Heap(堆)本質上是劃分在子區域中。

堆區域

區域描述最新一代-Young Generation (nursery space)新的或短暫的對象分配保留堆的一部分。垃圾被一個fast but stop-the-world YG的收集器進行回收。在young space中呆了足夠久的對象就會提升到old space。

注意:YG space的尺寸和GC頻率過高將會顯著影響程序的響應時間,從而導致JVM的暫停時間增加。

老一代-Old Generation (tenured space)heap的一部分留給了long-lived對象。垃圾通常通過平行或併發(多數時候)進行收集,諸如CMS或gencon (IBM JVM)。性能提示:根據應用程序的需求選擇並測試最佳的GC策略是非常重要的。例如,當切換到併發GC收集(如CMS或G1)可以顯著提高應用程序的平均響應時間(減少延遲)。

垂直打擊之JVM剖析

GC Collectors

選擇正確的collector或GC policy可以將程序的性能、可擴展性和可靠性優化到最佳狀態。許多應用程序對於響應時間延遲都很敏感,因此大多需要使用併發的回收器,例如HotSpot CMS或IBM GC policy balanced。

我們強烈建議您通過適當的性能和負載測試確定最合適的GC策略。應該在生產環境中執行全面監控策略,以跟蹤整體的JVM性能,並確定在之後需要改進的領域。

GC論據描述串行回收器-XX:+UseSerialGC (Oracle HotSpot)無論新舊回收器都使用單獨CPU,像是一種stop the world的時尚。

垂直打擊之JVM剖析

並行回收器(吞吐量回收器)-XX:+UseParallelGC-XX:+UseParallelOldGC

(Oracle Hotspot)-Xgcpolicy:optthruput

(IBmJ9, single space, stop-the-world)

旨在利用CPU的內核優勢。無論新舊回收器都使用多個Gcthreads(via –XX:ParallelGCThreads=n),從而更好地利用來自主機的可用的CPU內核來完成。注意:雖然回收時間可以顯著減少,但是有著大尺寸堆的程序面臨著large、stop-the-world、old回收,並且響應時間也受到影響。

垂直打擊之JVM剖析

確保適當的Permanent Generation / Metaspace和本地內存大小。密切監視你的PermGen、元空間和本機內存利用率,並調整到適合的最大容量。分析程序類加載器的大小,並尋找機會適當地減少元數據足跡。旨在最大限度地減少舊一代stop-the-world回收器對程序響應時間的影響。大多數使用CMS collector的老一代回收器與所述應用程序的執行同時進行。注意:YoungGen collections仍然有stop-the-world事件,因此需要適當的微調,以減少總JVM暫停時間。

垂直打擊之JVM剖析

Garbage First (G1) Collector

HotSpot G1 collector是專為是專為滿足用戶定義的垃圾回收(GC)高概率暫停時間設計的,同時實現高吞吐量。

最新的HotSpot collector將heap基本劃分到一組大小相等的堆區域,虛擬內存的每個區域連續範圍。它將回收壓縮的活動集中在heap區域,那裡充滿了可回收的對象(garbage first)。換句話說就是,這個區域有最低限度的“live”對象。

Oracle建議在以下例子和情況下使用G1 collector,尤其是對於目前正在使用CMS或parallel collectors的:

  • 專為large heaps(>= 6 GB),並限制GC延遲(暫停時間<= 0.5秒)的應用程序設計。
  • 超過50%的Java heap被實時數據佔用(對象不能被GC回收)。
  • 對象分析率和促進作用顯著變化。
  • 不期望過長的垃圾回收或壓縮停頓(超過0.5至1秒)。
垂直打擊之JVM剖析

Java Heap尺寸

你一定要知道沒有GC策略可以挽救Java Heap尺寸不足的現象。這些演習涉及到為不同的存儲空間(包括新舊不同的版本)配置最大和最小的容量,包括元數據和本地內存容量。這裡有一些建議準則:

  • 在32-bit或64-bit JVM之間進行明智的選擇。如果程序運行需要超過2GB內存,並且JVM暫停時間在可接受範圍內,可以考慮使用64-bit JVM。
  • 永遠將應用程序放在第一考慮。確保將其配置好,並根據程序的內存佔用量調整heap尺寸。建議通過性能和負載測試來衡量實時數據佔有量。
  • larger heap並不總是表現得更好、更快,因此不需要過度調整Java heap。並行中的JVM性能調優,找準機會減少或“spread”程序的內存佔有量,以保證JVM的平均響應時間<1%。
  • 對於32-bit JVM,為了從元數據和本地heap中留出一些內存,考慮2GB的最大heap尺寸。
  • 對於64-bit JVM,我們要想辦法在垂直和水平層面進行擴展,而不是試圖將Java heap尺寸增加到15GB以上。這種做法往往提供更好的吞吐量,更好地利用硬件,提高應用程序的故障切換功能。
  • 不許重複開發:充分利用開源以及商業故障排除的優勢和監控工具,使這些變成可能。APM(應用性能管理)產品在過去十年裡發展迅猛。

JDK 1.8 Metaspace指南

目標建議內存大小GC調整監控和故障排除

默認情況下,元空間內存空間是無界的,並使用可用於動態擴展的process或OS native memory。內存空間分成快並通過mmap被JVM進行存儲。我們建議保持默認設置,以動態調整模式為出發點,將簡化的尺寸與密切監測的應用程序元數據佔有量相結合,從而進行更好的容量規劃。新增一個JVM選項(-XX:MaxMetaspaceSize=),可以讓您限制分配給class metadata的本地內存。當面臨物理資源(RAM)緊張或類似於內存洩露的情況時,建議將它作為一個保障機制。對那種具有larger class metadata footprint或dynamic classloading的Java應用程序,我們建議通過新的JVM選項調整初始元空間大小 :-XX:MetaspaceSize=,例如:1GB。這種調整方法將有助於避免包括class metadata在內的早期垃圾回收,尤其是在Java應用程序的 “warm-up”期。

Hot Spots

垂直打擊之JVM剖析

故障診斷和監視

目標建議測量和監視應用程序YoungGen和OldGen內存佔用,包括GC活動。為您的應用程序決定正確的GC策略和Java堆大小。調整應用程序的內存佔用量,如live對象。

分析、監控您所使用的Java分析工具,如JProfiler、Java VisualVM或其他商業APM產品。允許通過–verbose:gc記錄JVM GC活動。您也可以使用類似GCMV(GC Memory Visualizer)的工具查看JVM的暫停時間和內存分配率。性能提示:過多的內存分配率可能意味著需要進行垂直和橫向擴展,或從多個JVM進程中分離出實時數據。

為了long-lived對象或long-term實時數據考慮,可以生成並分析JVM heap dump快照。Heap dump分析對於程序內存佔用(retention)的優化是非常有幫助的。

性能提示:由於從32位到64位,Java應用程序對heap 的需求會比原來高1.5倍。所以,在Java 1.7及以下的版本(這是默認的)中使用 -XX:+UseCompressedOops是非常重要的。這樣的參數調整大大減輕了64位JVM的性能壓力。

調查OutOfMemoryError 問題,尋找OldGen內存洩露的根源。使用類似Java VisualVM、Plumbr的工具(Java內存洩漏檢測器),分析可能存在的內容洩露。性能提示:要著重分析最大的Java對象上。要意識到降低內存佔有量就意味著提升性能,並降低GC活動。

垂直打擊之JVM剖析

使用類似 Memory Analyzer的工具生成並分析JVM heap dump快照。

垂直打擊之JVM剖析

Java併發性

Java併發性可以定義為程序同時執行多個任務的能力。對於大型的Java EE系統,這意味著執行多個用戶的業務功能的同時,實現最佳的吞吐量和性能的能力。

無論是硬件能力還是JVM穩定狀況,Java併發性問題可能引起程序的癱瘓,嚴重影響程序的整體性能和可用性。

垂直打擊之JVM剖析

Thread Lock Contention

當您評估Java應用程序的併發線程的穩定狀況時,你會經常遇到Thread lock contention的問題,這是目前最常見的Java併發問題。

例如:Thread lock contention會觸發non-stop,它會嘗試將一個缺少Java類(ClassNotFoundException的)加載到默認的JDK 1.7 ClassLoader。

垂直打擊之JVM剖析

如果您在成熟的技術環境中遇見像Thread Dump analysis這樣的問題,我們強烈建議您積極面對它。這個問題的根源通常不同於之前的Java synchronization to legitimate IO blocking或者其他的non-thread safe calls。Lock contention問題往往是另一個問題的“症狀”。

說到併發這一塊的問題,在這裡給大家推薦一個架構交流學習群:

650385180,裡面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成為架構師必備的知識體系。還能領取免費的學習資源,以下的知識體系圖也是在群裡獲取。相信對於已經工作和遇到技術瓶頸的碼友,在這個群裡一定有你需要的內容。

垂直打擊之JVM剖析

Java-level Deadlocks

真正的Java-level deadlocks是不太常見的,它同樣可以極大程度地影響應用程序的性能和穩定性。當遇到兩個或多個線程永遠阻塞的時候,就會觸發這樣的問題。這種情況不同於其他常見的那種“day-to-day”線程問題,例如 lock contention、threads waiting on blocking IO calls等等。真正的lock-ordering deadlock問題可以被看做如下:

垂直打擊之JVM剖析

Oracle HotSpot 和IBM JVM為大多數的deadlock detectors情況提供瞭解決方案,幫助您快速找出造成這種狀況的罪魁禍首的線程。遇到類似lock contention troubleshooting的問題,建議從諸如線程轉儲分析為出發點來解決該問題。

一旦找到造成問題的代碼根源,解決方案涉及lock-ordering條件尋址和來自JDK其他可用的併發編程技術,如java.util.concurrent.locks.ReentrantLock,提供了諸如tryLock()的方法。這種方法給予開發人員更大的靈活性,也為防止deadlock和thread lock “starvation”提供了更多方式。

垂直打擊之JVM剖析

Clock Time和CPU Burn

在進行JVM調優的同時,也有必要檢查應用程序的行為,更確切地說是最高clock time和CPU burn的貢獻者。

當Java垃圾回收和線程併發不再是壓力點,深入到你的應用程序代碼的執行模式,並專注於頂級響應時間貢獻者(也叫作clock time)是很重要的。檢查應用程序代碼的消CPU耗和Java 線程(CPU burn)也同樣至關重要。CPU使用率較高(>75%)是不正常的(良好的物理資源的利用率)。因為這往往意味著效率低下和容量問題。對於大型的Java EE企業應用,保持安全的CPU緩衝區是必要的,以應對突發的負載衝擊情況。

摒棄那些傳統的跟蹤方法,如在代碼中加入響應時間“日誌”。Java剖析工具和APM解決方案恰恰可以幫助您分析這類型的問題。這種方式更加高效、可靠。對於Java生產環境缺乏一個強大的APM解決方案。您仍然可以依賴諸如Java VisualVM的工具,通過多個快照進行thread dump分析,並使用OS CPU分析每個線程。

最後的建議是,不要妄圖同時解決所有的問題。列出排在最前面的5個clock time和CPU burn問題,然後尋找解決方案。

垂直打擊之JVM剖析

Application預算

其他關於Java應用程序性能的重要方面是穩定性和可靠性。在有著99.9%典型可用目標的SLA umbrella下,穩定和可靠對於程序的操作尤為重要。這些系統應該具有高容錯級別,並對應用和資源進行嚴格的預算,以防止發生多米諾效應。用這種方法可以防止一些這樣的情況,例如,一個業務流程使用所有可用的物理,中間件或JVM資源。

Hot Spots

垂直打擊之JVM剖析

垂直打擊之JVM剖析

超時管理

Java application與外部系統之間缺乏合理的超時時間,由於中間件和JVM線程消耗(blocking IO calls),可能導致嚴重的性能下降和中斷。合理的超時時間可以避免在遇到外部服務提供商速度緩慢的時候,Java線程等待太久。

垂直打擊之JVM剖析

垂直打擊之JVM剖析

垂直打擊之JVM剖析

工具

目標建議工具自動、實時地性能監控、調節、預警、趨勢分析、容量管理,等等Enterprise APM solutions(企業級APM解決方案)注意:APM解決方案提供了工具,這些現成的功能讓您實現以下大部分的Java性能目標。性能和負載測試商業性能測試解決方案Apache JMeterhttp://jmeter.apache.org/

JVM垃圾回收評估,內存分配率和故障排除Oracle Java VisualVMhttp://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/intro.htmlhttp://java.dzone.com/articles/profile-your-applications-java

Oracle Java Mission Control

http://www.oracle.com/technetwork/java/javaseproducts/mission-control/java-mission-control-wp-2008279.pdf

http://www.oracle.com/technetwork/java/javase/jmc53-release-notes-2157171.html

IBM Monitoring and Diagnostic Tools for Java (via IBM Support Assistant tool)

http://www-01.ibm.com/software/support/isa/

JVM verbose:gc logs

JVM argument : -verbose:gc

http://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html

IBM GCMV

https://www.ibm.com/developerworks/java/jdk/tools/gcmv/

JVM堆和類的元數據的內存洩漏分析Oracle Java VisualVM and Oracle Java Mission ControlIBM Monitoring and Diagnostic Tools for JavaMemory Analyzer (heap dump analysis, hprof and phd formats)

https://www.eclipse.org/mat/

https://www.ibm.com/developerworks/java/jdk/tools/memoryanalyzer/

JVM內存分析和堆容量評估Oracle Java VisualVM and Java Mission ControlIBM Monitoring and Diagnostic Tools for JavaJava profilers (JProfiler, YourKit)

http://en.wikipedia.org/wiki/JProfiler

http://www.yourkit.com/

Memory Analyzer (heap dump and application memory footprint analysis)

JVM和中間件併發故障,如thread lock contention和deadlocksOracle Java VisualVM and Oracle Java Mission Control (threads monitoring, thread dump snapshots)jstack, native OS signal such as kill -3 (thread dump snapshots)http://www.oracle.com/technetwork/java/javase/tooldescr-136044.html#gblfh

IBM Monitoring and Diagnostic Tools for Java

注意:強烈推薦大家關注如何執行一個JVM線程轉儲分析的相關知識。

Java應用程序clock time分析和評測Oracle Java VisualVM and Oracle Java Mission Control (build-in profiler, sampler and recorder)Java profilers (JProfiler, YourKit)Java應用程序和線程CPU burn分析Oracle Java VisualVM and Oracle Java Mission Control (CPU profiler)Java profilers (JProfiler, YourKit)注意:必要的時候,您還可以依賴JVM線程轉儲和OS CPU每個線程分析。

Java IO和remoting contention分析,包括超時管理評估和調整Oracle Java VisualVM and Oracle Java Mission Control(threads monitoring, thread dump snapshots)jstack, native OS signal such as kill -3 (thread dump snapshots)

IBM Monitoring and Diagnostic Tools for Java

注意:強烈推薦大家關注如何執行一個JVM線程轉儲分析的相關知識。

中間件,Java EE容器調整,如線程、JDBC數據源,等等Oracle Java VisualVM and Oracle Java Mission Control (extra focus on exposed Java EE container runtime MBeans)Java EE container administration and management console


分享到:


相關文章: