2019年Java大廠面試題講解(周陽) 之 JVM參數調優

      網友投稿 845 2025-04-08

      JVM參數調優

      前言

      JVM參數類型

      查看運行的Java程序,JVM參數是否開啟,具體值為多少?

      題外話(坑題)

      查看JVM默認參數

      工作中常用的JVM基本配置參數

      查看堆內存

      打印JVM默認參數

      生活常用調優參數

      GC垃圾收集

      Full GC垃圾回收

      -XX:SurvivorRatio

      -XX:NewRatio(了解)

      -XX:MaxTenuringThreshold

      前言

      你說你做過JVM調優和參數配置,請問如何盤點查看JVM系統默認值

      使用jps和jinfo進行查看

      -Xms:初始堆空間 -Xmx:堆最大值 -Xss:棧空間

      1

      2

      3

      -Xms 和 -Xmx最好調整一致,防止JVM頻繁進行收集和回收

      JVM參數類型

      標配參數(從JDK1.0 - Java12都在,很穩定)

      -version

      -help

      java -showversion

      X參數(了解)

      -Xint:解釋執行

      -Xcomp:第一次使用就編譯成本地代碼

      -Xmixed:混合模式

      XX參數(重點)

      Boolean類型

      公式:-XX:+ 或者-某個屬性 + 表示開啟,-表示關閉

      Case:-XX:-PrintGCDetails:表示關閉了GC詳情輸出

      key-value類型

      公式:-XX:屬性key=屬性value

      不滿意初始值,可以通過下列命令調整

      case:如何:-XX:MetaspaceSize=21807104:查看Java元空間的值

      查看運行的Java程序,JVM參數是否開啟,具體值為多少?

      首先我們運行一個HelloGC的java程序

      /** * @author: 輕狂書生FS * @create: 2020-04-19-12:14 */ public class HelloGC { public static void main(String[] args) throws InterruptedException { System.out.println("hello GC"); Thread.sleep(Integer.MAX_VALUE); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      2019年Java大廠面試題講解(周陽) 之 JVM參數調優

      然后使用下列命令查看它的默認參數

      jps:查看java的后臺進程 jinfo:查看正在運行的java程序

      1

      2

      具體使用:

      jps -l得到進程號

      1

      12608 com.moxi.interview.study.GC.HelloGC 15200 sun.tools.jps.Jps 15296 org.jetbrains.idea.maven.server.RemoteMavenServer36 4528 12216 org.jetbrains.jps.cmdline.Launcher 9772 org.jetbrains.kotlin.daemon.KotlinCompileDaemon

      1

      2

      3

      4

      5

      6

      查看到HelloGC的進程號為:12608

      我們使用jinfo -flag 然后查看是否開啟PrintGCDetails這個參數

      jinfo -flag PrintGCDetails 12608

      1

      得到的內容為

      -XX:-PrintGCDetails

      1

      上面提到了,-號表示關閉,即沒有開啟PrintGCDetails這個參數

      下面我們需要在啟動HelloGC的時候,增加 PrintGCDetails這個參數,需要在運行程序的時候配置JVM參數

      然后在VM Options中加入下面的代碼,現在+號表示開啟

      -XX:+PrintGCDetails

      1

      然后在使用jinfo查看我們的配置

      jps -l jinfo -flag PrintGCDetails 13540

      1

      2

      得到的結果為

      -XX:+PrintGCDetails

      1

      我們看到原來的-號變成了+號,說明我們通過 VM Options配置的JVM參數已經生效了

      使用下列命令,會把jvm的全部默認參數輸出

      jinfo -flags ***

      1

      題外話(坑題)

      兩個經典參數:-Xms 和 -Xmx,這兩個參數 如何解釋

      這兩個參數,還是屬于XX參數,因為取了別名

      -Xms 等價于 -XX:InitialHeapSize :初始化堆內存(默認只會用最大物理內存的64分1)

      -Xmx 等價于 -XX:MaxHeapSize :最大堆內存(默認只會用最大物理內存的4分1)

      查看JVM默認參數

      -XX:+PrintFlagsInitial

      主要是查看初始默認值

      公式

      java -XX:+PrintFlagsInitial -version

      java -XX:+PrintFlagsInitial(重要參數)

      -XX:+PrintFlagsFinal:表示修改以后,最終的值

      會將JVM的各個結果都進行打印

      如果有 := 表示修改過的, = 表示沒有修改過的

      工作中常用的JVM基本配置參數

      查看堆內存

      查看JVM的初始化堆內存 -Xms 和最大堆內存 Xmx

      /** * @author: 輕狂書生FS * @create: 2020-04-19-12:14 */ public class HelloGC { public static void main(String[] args) throws InterruptedException { // 返回Java虛擬機中內存的總量 long totalMemory = Runtime.getRuntime().totalMemory(); // 返回Java虛擬機中試圖使用的最大內存量 long maxMemory = Runtime.getRuntime().maxMemory(); System.out.println("TOTAL_MEMORY(-Xms) = " + totalMemory + "(字節)、" + (totalMemory / (double)1024 / 1024) + "MB"); System.out.println("MAX_MEMORY(-Xmx) = " + maxMemory + "(字節)、" + (maxMemory / (double)1024 / 1024) + "MB"); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      運行結果為:

      TOTAL_MEMORY(-Xms) = 257425408(字節)、245.5MB MAX_MEMORY(-Xmx) = 3790077952(字節)、3614.5MB

      1

      2

      -Xms 初始堆內存為:物理內存的1/64 -Xmx 最大堆內存為:系統物理內存的 1/4

      打印JVM默認參數

      使用 -XX:+PrintCommandLineFlags 打印出JVM的默認的簡單初始化參數

      比如我的機器輸出為:

      -XX:InitialHeapSize=266376000 -XX:MaxHeapSize=4262016000 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

      1

      生活常用調優參數

      -Xms:初始化堆內存,默認為物理內存的1/64,等價于 -XX:initialHeapSize

      -Xmx:最大堆內存,默認為物理內存的1/4,等價于-XX:MaxHeapSize

      -Xss:設計單個線程棧的大小,一般默認為512K~1024K,等價于 -XX:ThreadStackSize

      使用 jinfo -flag ThreadStackSize 會發現 -XX:ThreadStackSize = 0

      這個值的大小是取決于平臺的

      Linux/x64:1024KB

      OS X:1024KB

      Oracle Solaris:1024KB

      Windows:取決于虛擬內存的大小

      -Xmn:設置年輕代大小

      -XX:MetaspaceSize:設置元空間大小

      元空間的本質和永久代類似,都是對JVM規范中方法區的實現,不過元空間與永久代之間最大的區別在于:元空間并不在虛擬機中,而是使用本地內存,因此,默認情況下,元空間的大小僅受本地內存限制。

      -Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal

      但是默認的元空間大小:只有20多M

      為了防止在頻繁的實例化對象的時候,讓元空間出現OOM,因此可以把元空間設置的大一些

      -XX:PrintGCDetails:輸出詳細GC收集日志信息

      GC

      Full GC

      GC日志收集流程圖

      我們使用一段代碼,制造出垃圾回收的過程

      首先我們設置一下程序的啟動配置: 設置初始堆內存為10M,最大堆內存為10M

      -Xms10m -Xmx10m -XX:+PrintGCDetails

      1

      然后用下列代碼,創建一個 非常大空間的byte類型數組

      byte [] byteArray = new byte[50 * 1024 * 1024];

      1

      運行后,發現會出現下列錯誤,這就是OOM:java內存溢出,也就是堆空間不足

      Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.moxi.interview.study.GC.HelloGC.main(HelloGC.java:22)

      1

      2

      同時還打印出了GC垃圾回收時候的詳情

      [GC (Allocation Failure) [PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs] [Times: user=0.00 sys=0.00, real=0.03 secs] [GC (Allocation Failure) [PSYoungGen: 504K->480K(2560K)] 740K->772K(9728K), 0.0007815 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 480K->0K(2560K)] [ParOldGen: 292K->648K(7168K)] 772K->648K(9728K), [Metaspace: 3467K->3467K(1056768K)], 0.0080505 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] [GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 648K->648K(9728K), 0.0003035 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 648K->630K(7168K)] 648K->630K(9728K), [Metaspace: 3467K->3467K(1056768K)], 0.0058502 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] Heap PSYoungGen total 2560K, used 80K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000) eden space 2048K, 3% used [0x00000000ffd00000,0x00000000ffd143d8,0x00000000fff00000) from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000) to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000) ParOldGen total 7168K, used 630K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000) object space 7168K, 8% used [0x00000000ff600000,0x00000000ff69dbd0,0x00000000ffd00000) Metaspace used 3510K, capacity 4500K, committed 4864K, reserved 1056768K class space used 389K, capacity 392K, committed 512K, reserved 1048576K

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      問題發生的原因:

      因為們通過 -Xms10m 和 -Xmx10m 只給Java堆棧設置了10M的空間,但是創建了50M的對象,因此就會出現空間不足,而導致出錯

      同時在垃圾收集的時候,我們看到有兩個對象:GC 和 Full GC

      GC垃圾收集

      GC在新生區

      [GC (Allocation Failure) [PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs] [Times: user=0.00 sys=0.00, real=0.03 secs]

      1

      GC (Allocation Failure):表示分配失敗,那么就需要觸發年輕代空間中的內容被回收

      [PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs]

      1

      參數對應的圖為:

      Full GC垃圾回收

      Full GC大部分發生在養老區

      [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 648K->630K(7168K)] 648K->630K(9728K), [Metaspace: 3467K->3467K(1056768K)], 0.0058502 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

      1

      規律:

      [名稱: GC前內存占用 -> GC后內存占用 (該區內存總大小)]

      1

      當我們出現了老年代都扛不住的時候,就會出現OOM異常

      -XX:SurvivorRatio

      調節新生代中 eden 和 S0、S1的空間比例,默認為 -XX:SuriviorRatio=8,Eden:S0:S1 = 8:1:1

      加入設置成 -XX:SurvivorRatio=4,則為 Eden:S0:S1 = 4:1:1

      SurvivorRatio值就是設置eden區的比例占多少,S0和S1相同

      Java堆從GC的角度還可以細分為:新生代(Eden區,From Survivor區合To Survivor區)和老年代

      eden、SurvivorFrom復制到SurvivorTo,年齡 + 1

      首先,當Eden區滿的時候會觸發第一次GC,把還活著的對象拷貝到SurvivorFrom去,當Eden區再次觸發GC的時候會掃描Eden區合From區域,對這兩個區域進行垃圾回收,經過這次回收后還存活的對象,則直接復制到To區域(如果對象的年齡已經到達老年的標準,則賦值到老年代區),通知把這些對象的年齡 + 1

      清空eden、SurvivorFrom

      然后,清空eden,SurvivorFrom中的對象,也即復制之后有交換,誰空誰是to

      SurvivorTo和SurvivorFrom互換

      最后,SurvivorTo和SurvivorFrom互換,原SurvivorTo成為下一次GC時的SurvivorFrom區,部分對象會在From和To區域中復制來復制去,如此交換15次(由JVM參數MaxTenuringThreshold決定,這個參數默認為15),最終如果還是存活,就存入老年代

      -XX:NewRatio(了解)

      配置年輕代new 和老年代old 在堆結構的占比

      默認: -XX:NewRatio=2 新生代占1,老年代2,年輕代占整個堆的1/3

      -XX:NewRatio=4:新生代占1,老年代占4,年輕代占整個堆的1/5,NewRadio值就是設置老年代的占比,剩下的1個新生代

      新生代特別小,會造成頻繁的進行GC收集

      -XX:MaxTenuringThreshold

      設置垃圾最大年齡,SurvivorTo和SurvivorFrom互換,原SurvivorTo成為下一次GC時的SurvivorFrom區,部分對象會在From和To區域中復制來復制去,如此交換15次(由JVM參數MaxTenuringThreshold決定,這個參數默認為15),最終如果還是存活,就存入老年代

      這里就是調整這個次數的,默認是15,并且設置的值 在 0~15之間

      查看默認進入老年代年齡:jinfo -flag MaxTenuringThreshold 17344

      -XX:MaxTenuringThreshold=0:設置垃圾最大年齡。如果設置為0的話,則年輕對象不經過Survivor區,直接進入老年代。對于年老代比較多的應用,可以提高效率。如果將此值設置為一個較大的值,則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概念

      Java JVM

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel如何轉化成word
      下一篇:word神技能你知道哪些(word的技能都有什么)
      相關文章
      日韩精品亚洲专区在线观看| 亚洲av乱码一区二区三区| 亚洲人成网站18禁止久久影院| 婷婷亚洲综合五月天小说| 久久久青草青青国产亚洲免观 | 亚洲免费无码在线| 国产午夜亚洲精品| 亚洲91精品麻豆国产系列在线| 精品亚洲成AV人在线观看| 久久亚洲AV成人无码国产 | 亚洲中文字幕久久无码| 亚洲专区中文字幕| 亚洲娇小性色xxxx| 亚洲中文字幕无码av永久| 亚洲国产欧美国产综合一区| 亚洲熟妇无码AV| 亚洲人成电影网站国产精品| 国产成人亚洲综合在线| 国产亚洲Av综合人人澡精品| 亚洲片国产一区一级在线观看| 亚洲人成色7777在线观看不卡| 亚洲国产成人久久综合野外| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 亚洲国产精品嫩草影院| 亚洲色大成网站www尤物| 亚洲最大的成人网| 国产精品亚洲色图| 亚洲日本韩国在线| 国产亚洲成AV人片在线观黄桃| 亚洲AV无码精品色午夜在线观看| 亚洲AV无码成人专区片在线观看 | 亚洲AV无码国产一区二区三区| 欧美日韩亚洲精品| 亚洲AV之男人的天堂| 伊人久久综在合线亚洲91| 亚洲Av无码专区国产乱码DVD| 91亚洲导航深夜福利| 亚洲av成人综合网| 亚洲AV无码乱码在线观看裸奔| 亚洲AV永久无码精品| 亚洲成a人片在线网站|