日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM调优:运行参数,内存模型,mat、jps、jstat、jmap、jstack、jvisualvm工具的使用

發布時間:2025/1/21 编程问答 94 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM调优:运行参数,内存模型,mat、jps、jstat、jmap、jstack、jvisualvm工具的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JVM調優 - 工具篇

作者:張學亮

講解內容

  • 了解下我們為什么要學習JVM優化

  • 掌握jvm的運行參數以及參數的設置

  • 掌握jvm的內存模型(堆內存)

  • 掌握jamp命令的使用以及通過MAT工具進行分析

  • 掌握定位分析內存溢出的方法

  • 掌握jstack命令的使用

  • 掌握VisualJVM工具的使用

1、為什么要對jvm進行優化?

在本地開發環境中我們很少會遇到需要對jvm進行優化的需求,但是到了生產環境,我們

可能將有下面的需求:

  • 運行的應用“卡住了”,日志不輸出,程序沒有反應

  • 服務器的CPU負載突然升高

  • 在多線程應用下,如何分配線程的數量?

  • ……

在本次課程中,我們將對jvm有更深入的學習,我們不僅要讓程序能跑起來,而且是可以

跑的更快!可以分析解決在生產環境中所遇到的各種“棘手”的問題。

說明:本套課程使用的jdk版本為1.8.0_201。
PS:超過該版本oracle版jdk將收費。

2、jvm的運行參數

在jvm中有很多的參數可以進行設置,這樣可以讓jvm在各種環境中都能夠高效的運行。 絕大部分的參數保持默認即可。

2.1、三種參數類型

jvm的參數類型分為三類,分別是:

  • 標準參數
    • -help
    • -version
  • -X參數 (非標準參數)
    • -Xint
    • -Xcomp
  • -XX參數(使用率較高)
    • -XX:newSize
    • -XX:+UseSerialGC

2.2、標準參數

jvm的標準參數,一般都是很穩定的,在未來的JVM版本中不會改變,可以使用java -help 檢索出所有的標準參數。

$ java -help 用法: java [-options] class [args...](執行類)或 java [-options] -jar jarfile [args...](執行 jar 文件) 其中選項包括:-d32 使用 32 位數據模型 (如果可用)-d64 使用 64 位數據模型 (如果可用)-server 選擇 "server" VM默認 VM 是 server.-cp <目錄和 zip/jar 文件的類搜索路徑>-classpath <目錄和 zip/jar 文件的類搜索路徑>; 分隔的目錄, JAR 檔案和 ZIP 檔案列表, 用于搜索類文件。-D<名稱>=<>設置系統屬性-verbose:[class|gc|jni]啟用詳細輸出-version 輸出產品版本并退出-version:<>警告: 此功能已過時, 將在未來發行版中刪除。需要指定的版本才能運行-showversion 輸出產品版本并繼續-jre-restrict-search | -no-jre-restrict-search警告: 此功能已過時, 將在未來發行版中刪除。在版本搜索中包括/排除用戶專用 JRE-? -help 輸出此幫助消息-X 輸出非標準選項的幫助-ea[:<packagename>...|:<classname>]-enableassertions[:<packagename>...|:<classname>]按指定的粒度啟用斷言-da[:<packagename>...|:<classname>]-disableassertions[:<packagename>...|:<classname>]禁用具有指定粒度的斷言-esa | -enablesystemassertions啟用系統斷言-dsa | -disablesystemassertions禁用系統斷言-agentlib:<libname>[=<選項>]加載本機代理庫 <libname>, 例如 -agentlib:hprof另請參閱 -agentlib:jdwp=help 和 -agentlib:hprof=help-agentpath:<pathname>[=<選項>]按完整路徑名加載本機代理庫-javaagent:<jarpath>[=<選項>]加載 Java 編程語言代理, 請參閱 java.lang.instrument-splash:<imagepath>使用指定的圖像顯示啟動屏幕 有關詳細信息, 請參閱 http://www.oracle.com/technetwork/java/javase/documentation/index.html 。

有關詳細信息, 請參閱

2.2.1、實戰

實戰1:查看jvm版本

$ java -version java version "1.8.0_201" Java(TM) SE Runtime Environment (build 1.8.0_201-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)# `‐showversion`參數是表示,先打印版本信息,再執行后面的命令,在調試時非常有用, 后面會使用到。

實戰2:通過-D設置系統屬性參數

package cn.zxl.jvm;public class TestJVM {public static void main(String[] args) {String str = System.getProperty("str");if(str == null){System.out.println("dmgeo");}else{System.out.println(str);}System.gc();} }

進行編譯、測試:

打印結果:

上述配置就相當于命令行如下指令:

2.2.2、-server與-client參數

可以通過-server或-client設置jvm的運行參數。

  • 它們的區別是Server VM的初始堆空間會大一些,默認使用的是并行垃圾回收器,啟 動慢運行快。
  • Client VM相對來講會保守一些,初始堆空間會小一些,使用串行的垃圾回收器,它 的目標是為了讓JVM的啟動速度更快,但運行速度會比Serverm模式慢些。
  • JVM在啟動的時候會根據硬件和操作系統自動選擇使用Server還是Client類型的 JVM。 32位操作系統 如果是Windows系統,不論硬件配置如何,都默認使用Client類型的JVM。 如果是其他操作系統上,機器配置有2GB以上的內存同時有2個以上CPU的話默 認使用server模式,否則使用client模式。 64位操作系統 只有server類型,不支持client類型。

測試:

由于本機是64位系統,所以不支持client模式。

2.3、-X參數

jvm的-X參數是非標準參數,在不同版本的jvm中,參數可能會有所不同,可以通過java - X查看非標準參數。

D:\develop\workspace\java\zxl-jvm\zxl-jvm-test\src\main\java $ java -X-Xmixed 混合模式執行 (默認)-Xint 僅解釋模式執行-Xbootclasspath:<; 分隔的目錄和 zip/jar 文件>設置搜索路徑以引導類和資源-Xbootclasspath/a:<; 分隔的目錄和 zip/jar 文件>附加在引導類路徑末尾-Xbootclasspath/p:<; 分隔的目錄和 zip/jar 文件>置于引導類路徑之前-Xdiag 顯示附加診斷消息-Xnoclassgc 禁用類垃圾收集-Xincgc 啟用增量垃圾收集-Xloggc:<file> 將 GC 狀態記錄在文件中 (帶時間戳)-Xbatch 禁用后臺編譯-Xms<size> 設置初始 Java 堆大小-Xmx<size> 設置最大 Java 堆大小-Xss<size> 設置 Java 線程堆棧大小-Xprof 輸出 cpu 配置文件數據-Xfuture 啟用最嚴格的檢查, 預期將來的默認值-Xrs 減少 Java/VM 對操作系統信號的使用 (請參閱文檔)-Xcheck:jni 對 JNI 函數執行其他檢查-Xshare:off 不嘗試使用共享類數據-Xshare:auto 在可能的情況下使用共享類數據 (默認)-Xshare:on 要求使用共享類數據, 否則將失敗。-XshowSettings 顯示所有設置并繼續-XshowSettings:all顯示所有設置并繼續-XshowSettings:vm 顯示所有與 vm 相關的設置并繼續-XshowSettings:properties顯示所有屬性設置并繼續-XshowSettings:locale顯示所有與區域設置相關的設置并繼續-X 選項是非標準選項, 如有更改, 恕不另行通知。

2.3.1、-Xint、-Xcomp、-Xmixed

  • 在解釋模式(interpreted mode)下,-Xint標記會強制JVM執行所有的字節碼,當然這 會降低運行速度,通常低10倍或更多。
  • -Xcomp參數與它(-Xint)正好相反,JVM在第一次使用時會把所有的字節碼編譯成 本地代碼,從而帶來最大程度的優化。
    • 然而,很多應用在使用-Xcomp也會有一些性能損失,當然這比使用-Xint損失的 少,原因是-xcomp沒有讓JVM啟用JIT編譯器的全部功能。JIT編譯器可以對是否 需要編譯做判斷,如果所有代碼都進行編譯的話,對于一些只執行一次的代碼就 沒有意義了。
  • -Xmixed是混合模式,將解釋模式與編譯模式進行混合使用,由jvm自己決定,這是 jvm默認的模式,也是推薦使用的模式。

示例:強制設置運行模式

注意:編譯模式下,第一次執行會比解釋模式下執行慢一些,注意觀察。

2.4、-XX參數

XX參數也是非標準參數,主要用于jvm的調優和debug操作。
-XX參數的使用有2種方式,一種是boolean類型,一種是非boolean類型:

  • boolean類型
    • 格式:-XX:[+-]
    • 如:-XX:+DisableExplicitGC 表示禁用手動調用gc操作,也就是說調用 System.gc()無效
  • 非boolean類型
    • 格式:-XX:
    • 如:-XX:NewRatio=1 表示新生代和老年代的比值

用法:

2.5、-Xms與-Xmx參數

-Xms與-Xmx分別是設置jvm的堆內存的初始大小和最大大小。
-Xmx2048m:等價于-XX:MaxHeapSize,設置JVM最大堆內存為2048M。
-Xms512m:等價于-XX:InitialHeapSize,設置JVM初始堆內存為512M。
適當的調整jvm的內存大小,可以充分利用服務器資源,讓程序跑的更快。
示例:

D:\develop\workspace\java\zxl-jvm\zxl-jvm-test\src\main\java $ java -Xms512m -Xmx2048m cn.zxl.jvm.TestJVM dmgeo

2.6、查看jvm的運行參數

有些時候我們需要查看jvm的運行參數,這個需求可能會存在2種情況:

  • 第一,運行java命令時打印出運行參數;
  • 第二,查看正在運行的java進程的參數;

2.6.1、運行java命令時打印參數

運行java命令時打印參數,需要添加-XX:+PrintFlagsFinal參數即可。
java -XX:+PrintFlagsFinal -version


由上述的信息可以看出,參數有boolean類型和數字類型,值的操作符是=或:=,分別代表默認值和被修改的值。

修改參數VerifySharedSpaces的值
java -XX:+PrintFlagsFinal -XX:+VerifySharedSpaces -version

可以看到VerifySharedSpaces這個參數已經被修改了。

  • 開啟:
    java -XX:+PrintFlagsFinal -XX:+VerifySharedSpaces -version|findstr VerifySharedSpaces
  • 關閉:
    java -XX:+PrintFlagsFinal -XX:-VerifySharedSpaces -version|findstr VerifySharedSpaces

2.6.2、查看正在運行的jvm參數

如果想要查看正在運行的jvm就需要借助于jinfo命令查看。
首先,啟動一個tomcat用于測試,來觀察下運行的jvm參數。

在這里插入代碼片


訪問:localhoost:8080

  • 通過jps或者 jps ‐l查看java進程
  • 查看所有的參數,用法:jinfo ‐flags <進程id>
$ jinfo -flags 8172 Attaching to process ID 8172, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.101-b13 Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=197132288 -XX:MaxHeapSize=3143630848 -XX:MaxNewSize=1047527424 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=65536000 -XX:OldSize=131596288 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC Command line: -Djava.util.logging.config.file=D:\develop\apache-tomcat-7.0.76\conf\logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=D:\develop\apache-tomcat-7.0.76\endorsed -Dcatalina.base=D:\develop\apache-tomcat-7.0.76 -Dcatalina.home=D:\develop\apache-tomcat-7.0.76 -Djava.io.tmpdir=D:\develop\apache-tomcat-7.0.76\temp
  • 查看某一參數的值,用法:jinfo ‐flag <參數名> <進程id>

3、jvm的內存模型

jvm的內存模型在1.7和1.8有較大的區別,雖然本套課程是以1.8為例進行講解,但是我們 也是需要對1.7的內存模型有所了解,所以接下里,我們將先學習1.7再學習1.8的內存模型。

3.1、jdk1.7的堆內存模型

  • Young 年輕區(代)
    Young區被劃分為三部分,Eden區和兩個大小嚴格相同的Survivor區,其中, Survivor區間中,某一時刻只有其中一個是被使用的,另外一個留做垃圾收集時復制 對象用,在Eden區間變滿的時候, GC就會將存活的對象移到空閑的Survivor區間 中,根據JVM的策略,在經過幾次垃圾收集后,仍然存活于Survivor的對象將被移動 到Tenured區間。

  • Tenured 年老區
    Tenured區主要保存生命周期長的對象,一般是一些老的對象,當一些對象在Young 復制轉移一定的次數以后,對象就會被轉移到Tenured區,一般如果系統中用了 application級別的緩存,緩存中的對象往往會被轉移到這一區間。

  • Perm 永久區
    Perm代主要保存class,method,filed對象,這部份的空間一般不會溢出,除非一次性加載了很多的類,不過在涉及到熱部署的應用服務器的時候,有時候會遇到 java.lang.OutOfMemoryError : PermGen space 的錯誤,造成這個錯誤的很大原因 就有可能是每次都重新部署,但是重新部署后,類的class沒有被卸載掉,這樣就造 成了大量的class對象保存在了perm中,這種情況下,一般重新啟動應用服務器可以解決問題。

  • Virtual區
    最大內存和初始內存的差值,就是Virtual區。

3.2、jdk1.8的堆內存模型


由上圖可以看出,jdk1.8的內存模型是由2部分組成,年輕代 + 年老代。
年輕代:Eden + 2*Survivor
年老代:OldGen
在jdk1.8中變化最大的Perm區,用Metaspace(元數據空間)進行了替換。
需要特別說明的是:Metaspace所占用的內存空間不是在虛擬機內部,而是在本地內存空間中,這也是與1.7的永久代最大的區別所在。

3.3、為什么要廢棄1.7中的永久區?

官網給出了解釋:http://openjdk.java.net/jeps/122

This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.
移除永久代是為融合HotSpot JVM與 JRockit VM而做出的努力,因為JRockit沒有永久代,不需要配置永久代。

現實使用中,由于永久代內存經常不夠用或發生內存泄露,爆出異常java.lang.OutOfMemoryError: PermGen。
基于此,將永久區廢棄,而改用元空間,改為了使用本地內存空間。

3.4、通過jstat命令進行查看堆內存使用情況

jstat命令可以查看堆內存各部分的使用量,以及加載類的數量。命令的格式如下:
jstat [-命令選項] [vmid] [間隔時間/毫秒] [查詢次數]

3.4.1、查看class加載統計

$ jps

D:\develop\apache-tomcat-7.0.76\bin $ jstat -class 8212 Loaded Bytes Unloaded Bytes Time11844 21107.6 0 0.0 7.11

說明:

  • Loaded:加載class的數量
  • Bytes:所占用空間大小
  • Unloaded:未加載數量
  • Bytes:未加載占用空間
  • Time:時間

3.4.2、查看編譯統計

D:\develop\apache-tomcat-7.0.76\bin $ jstat -compiler 8212 Compiled Failed Invalid Time FailedType FailedMethod5043 1 0 28.86 1 org/apache/tomcat/util/IntrospectionUtils setProperty


說明:

  • Compiled:編譯數量。
  • Failed:失敗數量
  • Invalid:不可用數量
  • Time:時間
  • FailedType:失敗類型
  • FailedMethod:失敗的方法

3.4.3、垃圾回收統計

D:\develop\apache-tomcat-7.0.76\bin $ jstat -gc 8212S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 36352.0 38912.0 0.0 0.0 449536.0 83013.6 169984.0 45310.6 59028.0 58273.7 8192.0 8036.3 10 0.446 3 0.442 0.888


說明:

  • S0C:第一個Survivor區的大小(KB)
  • S1C:第二個Survivor區的大小(KB)
  • S0U:第一個Survivor區的使用大小(KB)
  • S1U:第二個Survivor區的使用大小(KB)
  • EC:Eden區的大小(KB)
  • EU:Eden區的使用大小(KB)
  • OC:Old區大小(KB)
  • OU:Old使用大小(KB)
  • MC:方法區大小(KB)
  • MU:方法區使用大小(KB)
  • CCSC:壓縮類空間大小(KB)
  • CCSU:壓縮類空間使用大小(KB)
  • YGC:年輕代垃圾回收次
  • FGC:老年代垃圾回收次數
  • FGCT:老年代垃圾回收消耗時間
  • GCT:垃圾回收消耗總時間

4、jmap的使用以及內存溢出分析

前面通過jstat可以對jvm堆的內存進行統計分析,而jmap可以獲取到更加詳細的內容,
如:內存使用情況的匯總、對內存溢出的定位與分析。

4.1、查看內存使用情況

D:\develop\apache-tomcat-7.0.76\bin $ jmap -heap 8212 Attaching to process ID 8212, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.101-b13using thread-local object allocation. Parallel GC with 4 thread(s)Heap Configuration: #堆內存配置信息MinHeapFreeRatio = 0MaxHeapFreeRatio = 100MaxHeapSize = 3143630848 (2998.0MB)NewSize = 65536000 (62.5MB)MaxNewSize = 1047527424 (999.0MB)OldSize = 131596288 (125.5MB)NewRatio = 2SurvivorRatio = 8MetaspaceSize = 21807104 (20.796875MB)CompressedClassSpaceSize = 1073741824 (1024.0MB)MaxMetaspaceSize = 17592186044415 MBG1HeapRegionSize = 0 (0.0MB)Heap Usage: PS Young Generation Eden Space:capacity = 460324864 (439.0MB)used = 85005936 (81.06797790527344MB)free = 375318928 (357.93202209472656MB)18.466509773410806% used From Space:capacity = 37224448 (35.5MB)used = 0 (0.0MB)free = 37224448 (35.5MB)0.0% used To Space:capacity = 39845888 (38.0MB)used = 0 (0.0MB)free = 39845888 (38.0MB)0.0% used PS Old Generation #老年代capacity = 174063616 (166.0MB)used = 46398096 (44.24867248535156MB)free = 127665520 (121.75132751464844MB)26.655826798404554% used19142 interned Strings occupying 1739112 bytes.

4.2、查看內存中對象數量及大小

  • 查看所有對象,包括活躍以及非活躍的
    jmap ‐histo <pid> | more

  • 查看活躍對象
    jmap ‐histo:live <pid> | more

D:\develop\apache-tomcat-7.0.76\bin $ jmap -histo:live 8212 | morenum #instances #bytes class name ----------------------------------------------1: 94334 12898664 [C2: 7855 7754536 [B3: 90965 2183160 java.lang.String4: 12566 1382144 java.lang.Class5: 15133 1331704 java.lang.reflect.Method6: 8457 1121552 [I7: 30353 971296 java.util.HashMap$Node8: 7480 864296 [Ljava.util.HashMap$Node;9: 14008 797072 [Ljava.lang.Object;10: 16005 640200 java.util.LinkedHashMap$Entry11: 9971 638144 java.net.URL12: 19843 634976 java.util.concurrent.ConcurrentHashMap$Node13: 5830 419760 java.lang.reflect.Field14: 8299 398352 org.apache.catalina.loader.ResourceEntry15: 4485 358800 java.lang.reflect.Constructor16: 16948 354952 [Ljava.lang.Class;17: 5245 293720 java.util.LinkedHashMap18: 4553 218544 java.util.HashMap19: 6442 206144 java.lang.ref.WeakReference20: 196 197920 [Ljava.util.concurrent.ConcurrentHashMap$Node;21: 4460 178400 java.lang.ref.SoftReference22: 2865 160440 java.lang.Class$ReflectionData23: 6383 153192 java.util.ArrayList24: 2933 148576 [Ljava.lang.String; -- More --

# 對象說明 B byte C char D double F float I int J long Z boolean [ 數組,如[I表示int[] [L+類名 其他對象

4.3、將內存使用情況dump到文件中

有些時候我們需要將jvm當前內存中的情況dump到文件中,然后對它進行分析,jmap也 是支持dump到文件中的。

#用法: jmap ‐dump:format=b,file=dumpFileName <pid>#示例 jmap ‐dump:format=b,file=dump.dat 8212

可以看到已經在D:\develop\workspace\java\zxl-jvm\zxl-jvm-test\data下生成了dump.dat的文件。

D:\develop\workspace\java\zxl-jvm\zxl-jvm-test\data $ jmap -dump:format=b,file=dump.dat 8212 Dumping heap to D:\develop\workspace\java\zxl-jvm\zxl-jvm-test\data\dump.dat ... Heap dump file createdD:\develop\workspace\java\zxl-jvm\zxl-jvm-test\data $ dir驅動器 D 中的卷是 軟件卷的序列號是 960C-77CED:\develop\workspace\java\zxl-jvm\zxl-jvm-test\data 的目錄2020/10/11 17:50 <DIR> . 2020/10/11 17:50 <DIR> .. 2020/10/11 17:50 78,462,398 dump.dat1 個文件 78,462,398 字節2 個目錄 593,156,988,928 可用字節

4.4、通過jhat對dump文件進行分析

在上一小節中,我們將jvm的內存dump到文件中,這個文件是一個二進制的文件,不方便查看,這時我們可以借助于jhat工具進行查看。

#用法: jhat ‐port <port> <file>

示例:

D:\develop\workspace\java\zxl-jvm\zxl-jvm-test\data $ jhat -port 9999 dump.dat Reading from dump.dat... Dump file created Sun Oct 11 17:50:10 CST 2020 Snapshot read, resolving... Resolving 617627 objects... Chasing references, expect 123 dots........................................................................................................................... Eliminating duplicate references........................................................................................................................... Snapshot resolved. Started HTTP server on port 9999 Server is ready.

打開瀏覽器進行訪問:http://localhost:9999/

在最后面有OQL查詢功能。

select s from java.lang.String s where s.value.length >= 10000

4.5、通過MAT工具對dump文件進行分析

4.5.1、MAT工具介紹

MAT(Memory Analyzer Tool),一個基于Eclipse的內存分析工具,是一個快速、功能豐 富的JAVA heap分析工具,它可以幫助我們查找內存泄漏和減少內存消耗。使用內存分析工具從眾多的對象中進行分析,快速的計算出在內存中對象的占用大小,看看是誰阻止 了垃圾收集器的回收工作,并可以通過報表直觀的查看到可能造成這種結果的對象。
官網地址:https://www.eclipse.org/mat/

4.5.2、下載安裝

下載地址:https://www.eclipse.org/mat/downloads.php


將下載得到的MemoryAnalyzer-1.10.0.20200225-win32.win32.x86_64.zip進行解壓:

4.5.3、使用

第一步:open

第二步:選擇要分析的堆轉儲文件

第三步:

第四步:點擊【Overview】

第五步:點擊【Dominator Tree】搜索對象

查看對象以及它的依賴:

查看可能存在內存泄露的分析:

總結

以上是生活随笔為你收集整理的JVM调优:运行参数,内存模型,mat、jps、jstat、jmap、jstack、jvisualvm工具的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。