【死磕JVM】什麼是JVM調優?

想要學習JVM調優,咱們必須提早知道他們的一些參數,這樣才方便咱們更好的去使用他們html

JVM經常使用命令行參數

JVM的命令行參數參考: docs.oracle.com/javase/8/do…java

1. 查看參數列表

虛擬機參數分爲基本和擴展兩類,在命令行中輸入 JAVA_HOME\bin\java就可獲得基本參數列表。 在命令行輸入 JAVA_HOME\bin\java –X就可獲得擴展參數列表。mysql

2. 基本參數說明:

-client,-server: 兩種Java虛擬機啓動方式,client模式啓動比較快,可是性能和內存管理相對較差,server模式啓動比較慢,可是運行性能比較高,windos上採用的是client模式,Linux採用server模式redis

-classpath -cp: 虛擬機在運行一個類的時候,須要將其轉入內存中,虛擬機搜索類的方式和順序:Bootstrap classes、Extension classes、User classes。 Bootstrap 中的路徑是虛擬機自帶的 jar 或 zip 文件,虛擬機首先搜索這些包文件,用System.getProperty("sun.boot.class.path")可獲得虛擬機搜索的包名。 Extension 是位於 jre\lib\ext 目錄下的 jar 文件,虛擬機在搜索完 Bootstrap 後就搜索該目錄下的 jar 文件。用 System. getProperty("java.ext.dirs」)可獲得虛擬機使用sql

Extension 搜索路徑。 User classes 搜索順序爲當前目錄、環境變量 CLASSPATH、-classpath。緩存

-classpath: 告訴虛擬機搜索目錄名、jar文檔名、zip文檔名服務器

-verbose[:class|gc|jni]: 在輸出設備上顯示虛擬機運行信息 -verbose:class 輸出虛擬機裝入的類的信息 -verbose:gc 在虛擬機發生內存回收時輸出設備信息,用來監視虛擬機內存回收的狀況 -verbose:jni 虛擬機調用native方法時輸出設置顯示信息,用來監視虛擬機調用本地方法的狀況markdown

-version:顯示可運行的虛擬機版本信息併發

-showversion:顯示版本信息以及幫助信息oracle

3. 擴展參數說明:

-Xmixed: 設置 -client 模式虛擬機對使用頻率高的方式進行 Just-In-Time 編譯和執行,對其餘方法使用解釋方式執行,該方式是虛擬機缺省模式

-Xint: 設置-client模式下運行的虛擬機以解釋方式執行類的字節碼,不將字節碼編譯爲本機碼,有可能會損失性能

-Xbootclasspath:path、-Xbootclasspath/a:path、-Xbootclasspath/p:path: 改變虛擬機裝載系統運行包 rt.jar,而從-Xbootclasspath 中設定的搜索路徑中裝載系統運行類。除非你本身能寫一個運行時,不然不會用到該參數。 /a:將在缺省搜索路徑後加上 path 中的搜索路徑。 /p:在缺省搜索路徑前先搜索 path 中的搜索路徑。

-Xnoclassgc: 關閉虛擬機對 class 的垃圾回收功能,有可能會致使OutOfMemoryError

-Xincgc: 啓動增量垃圾收集器,缺省是關閉的,增量垃圾收集器能減小偶然發生的長時間的垃圾回收形成的暫停時間,但增量垃圾收集器和應用程序併發執行,會佔用部分CPU在應用程序上的功能

-Xloggc:file: 將虛擬機每次垃圾回收的信息寫到日誌文件中,文件名由file指定,文件格式是平文件,內容和-verbose:gc 輸出內容相同

-Xms20M: 設置虛擬機可用內存堆的初始大小爲20M,大小爲1024的整數倍而且要大於1MB,可用K或者M爲單位來設置較大內存數,初始堆大小爲2MB,例如:-Xms256M

-Xmx20M: 設置虛擬機內存堆的最大可用大小,該值必須爲1024的整數倍,而且要大於2MB,可用K或者M爲單位來設置較大的內存數,例如:-Xmx81920K,-Xmx80M,當應用程序申請了大內存運行時虛擬機拋出 java.lang.OutOfMemoryError,就須要使用-Xmx來設置了

-Xss128K: 設置線程棧的大小,和-Xmx相似,能夠用K或M來設置較大的值,也能夠在Java中建立線程對象時設置棧的大小

-Xoss128k: 設置本地方法棧的大小爲128K,不過HotSpot不區分虛擬機棧和本地方法棧,因此這個參數對於HotSpot是無效的

-XX:PermSize=10M: 表示JVM初始分配的永久代的容量,必須以M爲單位

-XX:MaxPermSize=10M: 表示JVM容許分配的永久代的最大容量,必須以M爲單位,大部分狀況下這個參數默認爲64M

-XX:NewRatio=4: 表示設置年輕代:老年代的大小比值爲1:4,這意味着年輕代佔整個堆的1/5

-XX:SurvivorRatio=8: 表示設置2個Survivor區:1個Eden區的大小比值爲2:8,這意味着Survivor區佔整個年輕代的1/5,這個參數默認爲8

-Xmn20M: 表示設置年輕代的大小爲20M

-XX:+HeapDumpOnOutOfMemoryError: 表示可讓虛擬機在出現內存溢出異常時Dump出當前的堆內存轉儲快照

-XX:+UseG1GC: 表示讓JVM使用G1垃圾收集器

-XX:+PrintGCDetails: 表示在控制檯上打印出GC具體細節

-XX:+PrintGC: 表示在控制檯上打印出GC信息

-XX:PretenureSizeThreshold=3145728 表示對象大於3145728(3M)時直接進入老年代分配,這裏只能以字節做爲單位

-XX:MaxTenuringThreshold=1: 表示對象年齡大於1,自動進入老年代

虛擬機參數分類

標準: - 開頭,全部的HotSpot都支持 非標準:-X 開頭,特定版本HotSpot支持特定命令 不穩定:-XX 開頭,下個版本可能取消

例如:java -version、java -X

import java.util.List;
import java.util.LinkedList;

public class HelloGC {
  public static void main(String[] args) {
    System.out.println("HelloGC!");
    List list = new LinkedList();
    for(;;) {
      byte[] b = new byte[1024*1024];
      list.add(b);
    }
  }
}
複製代碼

在這裏插入圖片描述

區分概念:內存泄漏memory leak,內存溢出out of memory java -XX:+PrintCommandLineFlags HelloGC java -Xmn10M -Xms40M -Xmx60M -XX:+PrintCommandLineFlags -XX:+PrintGC HelloGC PrintGCDetails PrintGCTimeStamps PrintGCCauses java -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags HelloGC java -XX:+PrintFlagsInitial 默認參數值 java -XX:+PrintFlagsFinal 最終參數值 java -XX:+PrintFlagsFinal | grep xxx 找到對應的參數 java -XX:+PrintFlagsFinal -version |grep GC

調優前的基礎概念

1. 吞吐量: 用戶代碼時間 /(用戶代碼執行時間 + 垃圾回收時間) 2. 響應時間: STW(Stop The World)越短,響應時間越好

所謂的調優,首先本身要明確,想要的是什麼,是吞吐量仍是響應時間,仍是在知足必定的響應時間的狀況下,要求達到多大的吞吐量,通常來講根據業務類型去選擇對應的調優方式,好比網站須要的是響應時間優先,JDK1.8儘可能選G1,那若是是數據挖掘的須要使用的是吞吐量。

什麼是調優

在沒有接觸過調優以前咱們理解的JVM調優就是解決OOM問題,OOM只是JVM調優的一部分

  • 通常是根據需求進行JVM規劃和預調優
  • 優化運行JVM運行環境(慢,卡頓)
  • 解決JVM運行過程當中出現的各類問題(OOM)

首先的話,調優是從業務場景開始的,若是沒有業務場景的JVM調優都是不靠譜的,好比有時間在實際項目中,有不少個類,成千上萬個代碼,你怎麼知道具體是哪一個代碼有問題,就算咱們知道有段代碼頻繁的full gc,可是可能過一段時間就OOM了。

調優步驟:

  • 熟悉業務場景,選定垃圾回收器(沒有最好的垃圾回收器,只有最合適的垃圾回收器)

    1. 響應時間、停頓時間 [CMS G1 ZGC] (須要給用戶做響應)
    2. 吞吐量 = 用戶時間 /( 用戶時間 + GC時間) [PS]
  • 選擇回收器組合

  • 計算內存需求(設置內存大小 1.5G 16G)

  • 選定CPU:越高越好

  • 設定年代大小、升級年齡

  • 設定日誌參數

    1. -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
    2. 或者天天產生一個日誌文件

在生產環境中日誌文件,後面日誌名字,按照系統時間產生,循環產生,日誌個數五個,每一個大小20M,這樣的好處在於總體大小100M,能 控制總體文件大小

  • 觀察日誌狀況

調優案例

案例一

垂直電商,最高每日百萬訂單,處理訂單系統須要什麼樣的服務器配置

這個問題比較雞肋,由於不少不一樣的服務器配置都可以支撐

好比有一百萬個訂單,每一個小時不會產生很高的併發量,咱們尋找高峯時間,作一個假設100W訂單有72W訂單在高峯期產生,好比一個小時平均36W訂單,因此咱們內存選擇大小是按照巔峯時間選擇的,不少時間咱們可能就是去作壓測,實在不行就添加CPU和內存

案例二

12306遭遇春節大規模搶票應該如何支撐 訂單信息天天固定,能夠丟到緩存中,不一樣的業務邏輯有不一樣的業務設計,12306應該是中國併發量最大的秒殺網站,號稱併發100W,就是說每秒進行百萬次的業務邏輯的處理,估計淘寶一年最高的是54W併發。

若是解決這個問題呢,看下面所示:

CDN -》 LVS -》 NGINX -》 業務系統 -》每臺機器1W併發

普通電商的下單流程通常是:

訂單 -》下單-》 訂單系統減庫存 -》 等待用戶付款 這個事務若是同步的方式完成,TPS是支撐不了多長時間的

可是在12306裏面的模型是 下單-》 減庫存和訂單同時異步進行 -》 等待付款 異步是當你下完訂單以後,它一個線程去減庫存,另一個線程直接把你下單的信息扔到kafka或者redis裏面直接返回OK,你下單成功後等待你付款,何時你付款完成後面那些個訂單處理線程就會去裏面拿數據,這個處理完了就會持久化到Hbase或者是mysql,通常大流量的處理方法核心思想就是:分而治之

JVM優化

好比我有一個50萬PV的資料類網站(從磁盤提取文檔到內存)原服務器32位,1.5G的堆,用戶反饋網站比較緩慢,若是對它進行升級,新服務器64位,16G的堆內存,用戶仍是反饋卡頓,並且還比以前更嚴重,這個是由於什麼呢?通常來講不少用戶去瀏覽數據,不少數據會load到內存中,致使內存不足,頻繁的GC,STW時間過長,響應時間就會變慢,那咱們應該怎麼辦呢,使用 PS-> PN+CMS或者G1。

還有一個就是系統CPU常常100%,咱們要如何進行調優呢?

首先咱們能夠想到CPU100%那麼必定有線程在佔用系統資源

  1. 找出哪一個進程CPU高 (top命令)
  2. 該進程中的哪一個線程CPU高(top -Hp)
  3. 導出該線程的堆棧
  4. 查找哪一個方法(棧掙)比較消耗時間
  5. 工做線程佔比高 | 垃圾回收線程佔比高

總結

今天咱們只是講解了一些基本的操做,具體怎麼操做該怎麼辦呢?這一部分小農會在下一部分中進行講解,今天主要帶你們瞭解一些經常使用的參數,告訴你們怎麼去使用和一些前置知識,下面我會對這些問題作一個實戰性的講解,感興趣的小夥伴記得來個一鍵三連,感謝你們。

我是牧小農,怕什麼真理無窮,進一步有進一步的歡喜,你們加油!!!

相關文章
相關標籤/搜索