【JAVA進階架構師指南】之五:JVM性能調優

前言

  首先給你們說聲對不起,最近屬實太忙了,白天上班,晚上加班,回家還要收拾家裏,基本天天作完全部事兒都是凌晨一兩點了,沒有精力再搞其餘的了.
  好了,進入正題,讓咱們來聊聊JVM篇最後一個章節----JVM性能調優.童鞋們隨便打開一個大廠的招聘崗位JD,應該都會有JVM調優相關的描述,其實招聘方不必定要求候選人真的對JVM調優有實際調優經驗,可是至少得有思路,知道應該怎樣進行JVM層面的性能調優,說實話,知道如何進行JVM層面的性能調優的人,在面試中確實是有加分的.
  筆者在公司擔任面試官的時候,常常會看到候選人簡歷描述有JVM性能調優經驗,每當這個時候我都會問候選人一個問題,你是如何進行JVM性能調優的,不少童鞋的回答就是:噢,就是調整一下初始堆大小,新生代大小.這明顯不是筆者想要的答案,由於這根本就不叫JVM性能調優.童鞋們對號入座一下,對JVM調優僅僅是我上述說的那樣的,趕忙改一下簡歷,不要說本身會JVM性能調優.說實話,對JVM進行性能調優是對架構師的要求,甚至我敢說不少架構師都不必定有實際的JVM性能調優經驗.話很少說,讓咱們進入正題,咱們將從如下幾點來說解如何進行性能調優:前端

  • JVM性能調優的前提
  • JVM性能調優的預備知識
  • STW現象--Stop-The-World
  • 垃圾回收器的種類
  • 性能調優的目的
  • 如何進行性能調優

JVM性能調優的前提

  全部有經驗的架構師必定會有一個共識,JVM層面的性能調優必定是做爲最後的調優手段,在此以前,必定要確保系統其它方面都已經作到了極致,沒法再進行調優了,在這個前提下,纔會考慮JVM性能調優.這裏的其餘方面包括從前端到架構到代碼層面,我舉一些例子
從瀏覽器/APP角度可進行的優化有:java

  • 減小HTTP請求次數.
  • 使用客戶端緩存.
  • 瀏覽器啓用壓縮
  • 使用CDN加速
  • 動態資源和靜態資源分離

從系統層面可進行的優化有:面試

  • 啓用緩存,好比redis緩存數據
  • 使用集羣
  • 異步處理,好比引入消息隊列
  • 對代碼的優化

  以上列出的每一點,都能單獨拎出來說好久,可是博文篇幅問題,就不細說了,有興趣的童鞋能夠自行下去了解,咱們只着重說一下代碼優化,相信你們都知道,業界比較公認的編碼規範是阿里巴巴發佈的<java開發手冊>,裏面的內容都是阿里集團多年來血的教訓積累的精華,阿里集團內部有一個組織專門負責手冊的編寫和推廣,而且在不斷進行優化,最新版發佈到泰山版了(我看的時候仍是華山版,哈哈).若是有童鞋還不知道的,我建議去下載下來看一看.另外阿里雲上有<java開發手冊>的考試,若是經過了這個考試,說明你的編碼規範仍是不錯的,有興趣的童鞋能夠去試一下.
  除此以外,童鞋們還應該瞭解JVM自己爲咱們悄悄作的各類優化,其中最重要的是JIT編譯器的優化.我舉幾個例子,好比:方法內聯,逃逸分析等.默認狀況下,這些都是開啓的,若是不開啓這些功能,JVM性能會降低50%以上.除此以外,還有一些好比:棧上分配,TLAB等優化.這些內容因爲平時咱們開發中不會用到,是JVM在背後悄悄爲咱們作了優化,所以可能不少童鞋都不知道,可是若是想成爲一個合格的架構師,這些內容都是必需要知道的,畢竟架構師的知識廣度和深度決定了架構師的高度.
  除此以外,性能調優必定是基於性能測試的,空口說進行性能調優的都是耍流氓,只有在通過了實際的性能測試後,咱們才知道系統的瓶頸在哪裏,才知道那些方面須要進行調優,如何進行調優.經常使用的性能測試指標有TPS/QPS/吞吐量.而且默認全部的接口訪問都遵循二八原則(接口天天80%的訪問量集中在20%的時間內).redis

JVM性能調優的預備知識

  在進行JVM性能調優以前,咱們還得了解JVM,好比我前面的幾篇有關JVM的博文,都是須要掌握的,好比JVM內存模型,垃圾回收機制等等.另外咱們還須要掌握一些進行JVM分析的工具.其實在咱們安裝JDK的時候,JDK已經爲咱們準備了許多有用的性能調優監控工具,咱們能夠看一下JDK安裝目錄下的bin目錄:
file算法

  • jps: 主要用來輸出JVM中運行的進程狀態信息
  • jstack: 主要用來查看某個Java進程內的線程堆棧信息
  • jmap: 用來查看堆內存使用情況,通常結合jhat使用
  • jstat: JVM統計監測工具
  • jconsole: 圖形化的統計工具
  • jvisualvm: 比jconsole功能更強的圖形化的監控工具

  另外咱們須要知道,當JVM發生OOM異常時,可使用命令生成一個.hprof後綴的dump文件,該文件是某個時間節點的heap的快照,咱們可使用VisualVM來查看,也能夠用第三方提供的一些工具,好比eclipse的MAT來查看內存溢出的緣由.瀏覽器

STW現象

  所謂STW現象(Stop-The-World)是指在執行垃圾收集算法時,Java應用程序的其餘全部線程(除了垃圾收集線程以外的線程)都被掛起.此時,系統只容許GC線程繼續運行,其餘線程所有暫停,等待GC線程執行完畢後才能繼續執行.這些工做都是由虛擬機在後臺自動發起和自動完成的,是在用戶不可見的狀況下把用戶正常工做的線程所有停掉,舉個例子,某個接口平時可能只須要50ms的RT,突然某次調用花費了200ms.所以STW對實時性要求很高的系統來講是難以接受的.緩存

垃圾回收器的種類

  既然有STW現象,那麼有沒有解決方案呢?這就是咱們接下來要講的,垃圾回收器的種類,目前爲止,JVM一共爲咱們提供了七種垃圾回收器,其中年輕代有三種,老年代有三種,另外還有一種特殊的G1:
file
file
file微信

  固然,在更新版本的JDK中還有一種ZGC,爲將來垃圾回收器提供了一種趨勢,有興趣的童鞋能夠自行了解.架構

性能調優的目的和具體過程

  有了前面的鋪墊,終於來到了咱們最重要的正題:如何進行JVM性能調優?在我看來JVM調優的具體步驟分爲以下幾步:併發

  • 肯定調優的目的,選擇合適的GC collector
  • 調整JVM heap的大小
  • 調整young generation在整個JVM heap中所佔的比重.

肯定調優的目的,選擇合適的GC collector

  因爲每種垃圾回收器的特性並不相同,所以咱們須要根據咱們的調優目的選擇合適的垃圾回收器,好比,咱們須要下降STW的停頓時間,那咱們就不能選用串行和並行的垃圾回收器,而應該選用併發的垃圾回收器,即CMS,與之搭配的新生代垃圾回收器就應該選用ParNew.目前通常主流互聯網公司都是用CMS垃圾回收器.

調整JVM heap的大小

  肯定了垃圾回收器的類型,就須要調整JVM heap的大小,在這一步的時候,首先咱們須要瞭解JVM相關的一些指令,好比能夠在啓動java程序時加上
-XX:+HeapDumpOnOutOfMemoryError,當發生OOM時,JVM會自動爲咱們生成DUMP文件
-XX:+PrintGCDetails -Xloggc:D:\gclogger\gc.log -XX:+PrintGCDateStamps 生成GC日誌
-Xms2g -Xmx2g 固然,還應該要根據實際狀況設置heap的最大最小值,童鞋們要知道,默認狀況下,java程序啓動的最小heap大小爲1/64物理內存,最大值爲1/4物理內存,通常要求咱們最大最小值保持一致,避免JVM頻繁擴容和縮容致使沒必要要的性能浪費.

調整young generation在整個JVM heap中所佔的比重.

  肯定了heap的大小,還須要肯定新生代的比重
–Xmn1500m -XX:MetaspaceSize=150M

  固然,再厲害的架構師也不可能一次就調整得出最佳的JVM配置參數,而是應該多設置幾組不一樣的值,放到生產環境(或者和生產環境同樣的環境,好比阿里內部有預發環境,和生產環境保持一致)進行性能測試,經過對比結果得出最佳的JVM性能調優參數,完成JVM性能調優.

總結

  讀完了本篇文章,我相信童鞋們應該或多或少會有些收穫.掌握JVM調整的核心步驟:

  • 肯定調優的目的,選擇合適的GC collector
  • 調整JVM heap的大小
  • 調整young generation在整個JVM heap中所佔的比重.
      不瞭解如何進行JVM的調優的人,把本文內容好好理解後,能讓面試官另眼相看;瞭解JVM調優,可是條理不清晰的童鞋,可能會對JVM調優有更清晰的認識.總而言之,筆者認爲本文是一篇滿滿的乾貨,網上許多講JVM調優的博文,並無這麼系統的講解過真正應該如何進行JVM調優.固然筆者能力有限,如文章有錯誤,歡迎指正,畢竟是人就會犯錯.
      PS:一入JVM深似海,今後再也出不來.對JVM有興趣的童鞋,能夠鑽研,可是在經驗不足以前,不建議太過深刻了解JVM,不然會耽誤本身.固然,立志要成爲一名牛逼的架構師,這些都是必需要會的.
      本文咱們講完了JVM,下一篇開始,讓咱們繼續學習JAVA鎖相關的內容.
      若是以爲博主寫的不錯,歡迎關注博主微信公衆號,博主會不按期分享技術乾貨!
    file

本文由博客一文多發平臺 OpenWrite 發佈!

相關文章
相關標籤/搜索