jdk8 Metaspace 調優

簡介

從JDK8開始,永久代(PermGen)的概念被廢棄掉了,取而代之的是一個稱爲Metaspace的存儲空間。Metaspace使用的是本地內存,而不是堆內存,也就是說在默認狀況下Metaspace的大小隻與本地內存大小有關。固然你也能夠經過如下的幾個參數對Metaspace進行控制:html

  1. -XX:MetaspaceSize=N 
    這個參數是初始化的Metaspace大小,該值越大觸發Metaspace GC的時機就越晚。隨着GC的到來,虛擬機會根據實際狀況調控Metaspace的大小,可能增長上線也可能下降。在默認狀況下,這個值大小根據不一樣的平臺在12M到20M浮動。使用java -XX:+PrintFlagsInitial命令查看本機的初始化參數,-XX:Metaspacesize爲21810376B(大約20.8M)。java

  2. -XX:MaxMetaspaceSize=N 
    這個參數用於限制Metaspace增加的上限,防止由於某些狀況致使Metaspace無限的使用本地內存,影響到其餘程序。在本機上該參數的默認值爲4294967295B(大約4096MB)。web

  3. -XX:MinMetaspaceFreeRatio=N 
    當進行過Metaspace GC以後,會計算當前Metaspace的空閒空間比,若是空閒比小於這個參數,那麼虛擬機將增加Metaspace的大小。在本機該參數的默認值爲40,也就是40%。設置該參數能夠控制Metaspace的增加的速度,過小的值會致使Metaspace增加的緩慢,Metaspace的使用逐漸趨於飽和,可能會影響以後類的加載。而太大的值會致使Metaspace增加的過快,浪費內存。oracle

  4. -XX:MaxMetasaceFreeRatio=N 
    當進行過Metaspace GC以後, 會計算當前Metaspace的空閒空間比,若是空閒比大於這個參數,那麼虛擬機會釋放Metaspace的部分空間。在本機該參數的默認值爲70,也就是70%。框架

  5. -XX:MaxMetaspaceExpansion=N 
    Metaspace增加時的最大幅度。在本機上該參數的默認值爲5452592B(大約爲5MB)。ide

  6. -XX:MinMetaspaceExpansion=N 
    Metaspace增加時的最小幅度。在本機上該參數的默認值爲340784B(大約330KB爲)。函數

測試代碼

下面會針對這個參數對Metaspace作一個粗略的展現。測試

 
  1. import java.util.ArrayList;ui

  2. import java.util.List;this

  3.  
  4. import org.objectweb.asm.ClassWriter;

  5. import org.objectweb.asm.MethodVisitor;

  6. import org.objectweb.asm.Opcodes;

  7.  
  8. /*

  9. * 繼承ClassLoader是爲了方便調用defineClass方法,由於該方法的定義爲protected

  10. * */

  11. public class Metaspace extends ClassLoader {

  12. public static void main(String[] args) {

  13. // 類持有

  14. List<Class<?>> classes = new ArrayList<Class<?>>();

  15. // 循環1000w次生成1000w個不一樣的類。

  16. for (int i = 0; i < 10000000; ++i) {

  17. ClassWriter cw = new ClassWriter(0);

  18. // 定義一個類名稱爲Class{i},它的訪問域爲public,父類爲java.lang.Object,不實現任何接口

  19. cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,

  20. "java/lang/Object", null);

  21. // 定義構造函數<init>方法

  22. MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",

  23. "()V", null, null);

  24. // 第一個指令爲加載this

  25. mw.visitVarInsn(Opcodes.ALOAD, 0);

  26. // 第二個指令爲調用父類Object的構造函數

  27. mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",

  28. "<init>", "()V", false);

  29. // 第三條指令爲return

  30. mw.visitInsn(Opcodes.RETURN);

  31. mw.visitMaxs(1, 1);

  32. mw.visitEnd();

  33.  
  34. Metaspace test = new Metaspace();

  35. byte[] code = cw.toByteArray();

  36. // 定義類

  37. Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length);

  38. classes.add(exampleClass);

  39. }

  40. }

  41. }

  42.  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

上面的程序的大體意思是,不斷的生成新的類, 而後讓類加載器去加載這個類,同時將其保存下來,避免GC回收掉。這裏使用到了ASM框架

測試參數

在運行該程序的時候加上以下的JVM參數,第一個參數用於打印GC日誌,第二個參數用於打印對應的時間戳。

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps

運行程序後,打印出的第一行日誌顯示,

2015-07-05T16:26:53.708+0800: [GC (Metadata GC Threshold) [PSYoungGen: 13978K->3229K(38400K)] 13978K->3237K(125952K), 0.0043062 secs] [Times: user=0.06 sys=0.02, real=0.00 secs] 
2015-07-05T16:26:53.712+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 3229K->0K(38400K)] [ParOldGen: 8K->3111K(60928K)] 3237K->3111K(99328K), [Metaspace: 5699K->5699K(1064960K)], 0.0110314 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

奇怪的事情發生了,這裏面顯示的Metaspace大小爲1064960K,將近1G,而不是前面提到的默認值20M左右。繼續運行一段時間後出現了以下的異常,

Exception in thread "main" java.lang.OutOfMemoryError: Compressed class space
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at Metaspace.main(Metaspace.java:37)

根據http://itdoc.hitachi.co.jp/manuals/link/has_v101001/0344211De/compressedclassspacesize.htm 
的描述,在JVM使用-XX:+UseCompressedClassPointers和-XX:+UseCompressedOops開啓Compressed Class的功能後,會在Metaspace中開闢出一塊新的空間(Compressed Class Space),上面的錯誤正是因爲這個空間出現了OutOfMemory,能夠經過設置-XX:CompressedClassSpaceSize(默認值爲1G)的大小或者-XX:-UseCompressedClassPointers來關閉該功能。 
爲了避免影響下面的測試,暫時使用-XX:-UseCompressedClassPointers來關閉。

這時JVM參數變爲了,

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:-UseCompressedClassPointers

再一次運行程序,出現以下日誌

2015-07-05T17:38:31.030+0800: [GC (Metadata GC Threshold) [PSYoungGen: 21301K->4984K(38400K)] 21301K->4992K(125952K), 0.0041727 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2015-07-05T17:38:31.034+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 4984K->0K(38400K)] [ParOldGen: 8K->4789K(64512K)] 4992K->4789K(102912K), [Metaspace: 6922K->6922K(22528K)], 0.0147936 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

初始的Metaspace的大小變爲了20M左右。由此猜測以前出現的問題是否是因爲開啓了壓縮功能,而默認值-XX:CompressedClassSpaceSize=1G,其大於-XX:MetaspaceSize=20M,因此MetaspaceSize被設置爲了1G。

-XX:MetaspaceSize的使用

添加JVM參數,-XX:MetaspaceSize=100m, 這時的JVM參數變爲,

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:-UseCompressedClassPointers -XX:MetaspaceSize=50M

運行後出現的日誌爲, 

2015-07-05T17:53:20.430+0800: [GC (Allocation Failure) [PSYoungGen: 33280K->5100K(38400K)] 33280K->7635K(125952K), 0.0076185 secs] [Times: user=0.03 sys=0.03, real=0.01 secs]  

2015-07-05T17:53:20.511+0800: [GC (Metadata GC Threshold) [PSYoungGen: 24676K->5102K(71680K)] 27211K->11885K(159232K), 0.0085707 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]  

2015-07-05T17:53:20.519+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5102K->0K(71680K)] [ParOldGen: 6782K->11703K(67584K)] 11885K->11703K(139264K), [Metaspace: 13581K->13581K(51200K)], 0.0442425 secs] [Times: user=0.19 sys=0.00, real=0.04 secs]


默認的初始值變爲了50M,可見設置的參數生效了。

-XX:MaxMetaspaceSize的使用

添加JVM參數,-XX:MaxMetaspaceSize=100m, 這時的JVM參數變爲, 

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:-UseCompressedClassPointers -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=100m


運行後出現的日誌爲, 

2015-07-05T18:04:10.000+0800: [GC (Allocation Failure) [PSYoungGen: 33280K->5116K(38400K)] 33280K->7627K(125952K), 0.0069565 secs] [Times: user=0.08 sys=0.00, real=0.01 secs]  

2015-07-05T18:04:10.086+0800: [GC (Metadata GC Threshold) [PSYoungGen: 24689K->5102K(71680K)] 27199K->11917K(159232K), 0.0092239 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]  

2015-07-05T18:04:10.095+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5102K->0K(71680K)] [ParOldGen: 6814K->11703K(74240K)] 11917K->11703K(145920K), [Metaspace: 13581K->13581K(51200K)], 0.0636790 secs] [Times: user=0.20 sys=0.00, real=0.06 secs]  

2015-07-05T18:04:10.297+0800: [GC (Metadata GC Threshold) [PSYoungGen: 37664K->5106K(71680K)] 49367K->19785K(145920K), 0.0066032 secs] [Times: user=0.11 sys=0.00, real=0.01 secs]  

2015-07-05T18:04:10.304+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5106K->0K(71680K)] [ParOldGen: 14679K->19664K(129536K)] 19785K->19664K(201216K), [Metaspace: 21181K->21181K(86016K)], 0.0752276 secs] [Times: user=0.45 sys=0.02, real=0.08 secs]  

2015-07-05T18:04:10.454+0800: [GC (Metadata GC Threshold) [PSYoungGen: 19414K->4219K(82432K)] 39079K->23884K(211968K), 0.0048493 secs] [Times: user=0.11 sys=0.00, real=0.01 secs]  

2015-07-05T18:04:10.459+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 4219K->0K(82432K)] [ParOldGen: 19664K->23672K(187392K)] 23884K->23672K(269824K), [Metaspace: 24981K->24981K(102400K)], 0.0569726 secs] [Times: user=0.33 sys=0.00, real=0.06 secs]  

2015-07-05T18:04:10.516+0800: [GC (Last ditch collection) [PSYoungGen: 0K->0K(88064K)] 23672K->23672K(275456K), 0.0021137 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]  

2015-07-05T18:04:10.518+0800: [Full GC (Last ditch collection) [PSYoungGen: 0K->0K(88064K)] [ParOldGen: 23672K->23655K(274944K)] 23672K->23655K(363008K), [Metaspace: 24981K->24981K(102400K)], 0.1025192 secs] [Times: user=0.69 sys=0.00, real=0.10 secs]  

Exception in thread "main" java.lang.OutOfMemoryError: Metaspace 

    at java.lang.ClassLoader.defineClass1(Native Method) 

    at java.lang.ClassLoader.defineClass(ClassLoader.java:760) 

    at java.lang.ClassLoader.defineClass(ClassLoader.java:642) 

    at Metaspace.main(Metaspace.java:37)


當Metaspace的空間增加到100M的時候,還須要繼續增加,可是因爲以前設置了Metaspace的最大值爲100M,所以拋出了上面的異常。

-XX:MinMetaspaceFreeRatio的使用

添加JVM參數,-XX:MinMetaspaceFreeRatio=65(注意此時-XX:MaxMetaspaceFreeRatio爲70,min須要小於max,因此設置爲), 這時的JVM參數變爲 

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:-UseCompressedClassPointers -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=100m -XX:MinMetaspaceFreeRatio=65


運行後的日誌爲, 

2015-07-05T18:32:06.476+0800: [GC (Allocation Failure) [PSYoungGen: 33280K->5100K(38400K)] 33280K->7595K(125952K), 0.0093795 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]  

2015-07-05T18:32:06.555+0800: [GC (Metadata GC Threshold) [PSYoungGen: 24677K->5102K(71680K)] 27172K->11893K(159232K), 0.0077681 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]  

2015-07-05T18:32:06.563+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5102K->0K(71680K)] [ParOldGen: 6790K->11703K(71680K)] 11893K->11703K(143360K), [Metaspace: 13581K->13581K(51200K)], 0.0424761 secs] [Times: user=0.16 sys=0.02, real=0.04 secs]  

2015-07-05T18:32:06.826+0800: [GC (Metadata GC Threshold) [PSYoungGen: 55855K->5115K(71680K)] 67559K->23867K(143360K), 0.0121986 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]  

2015-07-05T18:32:06.838+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5115K->0K(71680K)] [ParOldGen: 18751K->23672K(128000K)] 23867K->23672K(199680K), [Metaspace: 24981K->24981K(102400K)], 0.0786608 secs] [Times: user=0.31 sys=0.00, real=0.08 secs]  

2015-07-05T18:32:06.917+0800: [GC (Last ditch collection) [PSYoungGen: 0K->0K(81920K)] 23672K->23672K(209920K), 0.0018780 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]  

2015-07-05T18:32:06.919+0800: [Full GC (Last ditch collection) [PSYoungGen: 0K->0K(81920K)] [ParOldGen: 23672K->23655K(179200K)] 23672K->23655K(261120K), [Metaspace: 24981K->24981K(102400K)], 0.0771198 secs] [Times: user=0.34 sys=0.00, real=0.08 secs]  

Exception in thread "main" java.lang.OutOfMemoryError: Metaspace 

    at java.lang.ClassLoader.defineClass1(Native Method) 

    at java.lang.ClassLoader.defineClass(ClassLoader.java:760) 

    at java.lang.ClassLoader.defineClass(ClassLoader.java:642) 

    at Metaspace.main(Metaspace.java:37)

彷佛與以前沒什麼區別,可是仔細能夠發現相比於不設置該參數少了一次FullGC。 
若是將該參數設置的很小,好比10,則大約能夠經歷7次FullGC。 
後面會討論這個區別。

-XX:MinMetaspaceExpansion

去掉以前設置的-XX:MinMetaspaceFreeRatio,同時設置-XX:MinMetaspaceExpansion=100M,修改-XX:MaxMetaspaceSize爲300M,此時的JVM參數爲,

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:-UseCompressedClassPointers -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=300M -XX:MinMetaspaceExpansion=100M

運行後的日誌爲,

2015-07-05T18:53:25.466+0800: [GC (Allocation Failure) [PSYoungGen: 33280K->5100K(38400K)] 33280K->7607K(125952K), 0.0067215 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2015-07-05T18:53:25.553+0800: [GC (Metadata GC Threshold) [PSYoungGen: 24676K->5102K(71680K)] 27183K->11881K(159232K), 0.0080541 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2015-07-05T18:53:25.561+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5102K->0K(71680K)] [ParOldGen: 6778K->11771K(73216K)] 11881K->11771K(144896K), [Metaspace: 13580K->13580K(51200K)], 0.0469926 secs] [Times: user=0.14 sys=0.00, real=0.05 secs] 
2015-07-05T18:53:25.875+0800: [GC (Allocation Failure) [PSYoungGen: 66560K->5115K(71680K)] 78331K->26463K(144896K), 0.0146596 secs] [Times: user=0.06 sys=0.00, real=0.02 secs] 
2015-07-05T18:53:26.110+0800: [GC (Metadata GC Threshold) [PSYoungGen: 48338K->5113K(91648K)] 69686K->35925K(164864K), 0.0151956 secs] [Times: user=0.05 sys=0.01, real=0.02 secs] 
2015-07-05T18:53:26.125+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 5113K->0K(91648K)] [ParOldGen: 30811K->35633K(147456K)] 35925K->35633K(239104K), [Metaspace: 36381K->36381K(153600K)], 0.1574835 secs] [Times: user=0.66 sys=0.00, real=0.16 secs] 
2015-07-05T18:53:26.818+0800: [GC (Allocation Failure) [PSYoungGen: 86528K->5109K(91648K)] 122161K->54855K(239104K), 0.0200557 secs] [Times: user=0.06 sys=0.00, real=0.02 secs] 
2015-07-05T18:53:27.015+0800: [GC (Metadata GC Threshold) [PSYoungGen: 29014K->10133K(127488K)] 78760K->59879K(274944K), 0.0116375 secs] [Times: user=0.05 sys=0.02, real=0.01 secs] 
2015-07-05T18:53:27.027+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 10133K->0K(127488K)] [ParOldGen: 49745K->59524K(221696K)] 59879K->59524K(349184K), [Metaspace: 59182K->59182K(256000K)], 0.2163024 secs] [Times: user=1.05 sys=0.00, real=0.22 secs] 
2015-07-05T18:53:27.691+0800: [GC (Metadata GC Threshold) [PSYoungGen: 56721K->12448K(127488K)] 116245K->71972K(349184K), 0.0139748 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2015-07-05T18:53:27.705+0800: [Full GC (Metadata GC Threshold) [PSYoungGen: 12448K->0K(127488K)] [ParOldGen: 59524K->71563K(306176K)] 71972K->71563K(433664K), [Metaspace: 70582K->70582K(307200K)], 0.1479683 secs] [Times: user=0.55 sys=0.00, real=0.15 secs] 
2015-07-05T18:53:27.853+0800: [GC (Last ditch collection) [PSYoungGen: 0K->0K(144384K)] 71563K->71563K(450560K), 0.0045973 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2015-07-05T18:53:27.857+0800: [Full GC (Last ditch collection) [PSYoungGen: 0K->0K(144384K)] [ParOldGen: 71563K->71546K(386048K)] 71563K->71546K(530432K), [Metaspace: 70582K->70582K(307200K)], 0.2734107 secs] [Times: user=1.65 sys=0.00, real=0.27 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at Metaspace.main(Metaspace.java:37)

能夠看出每次Metaspace空間的增加都在100MB左右,經歷了3次的FullGC以後空間就達到了設置的上限300MB。

-XX:MinMetaspaceFreeRatio和-XX:MinMetaspaceExpansion

爲了說明這兩者有什麼影響設置以下參數,

-XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:-UseCompressedClassPointers -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=500m -XX:MinMetaspaceExpansion=50M -XX:MaxMetaspaceExpansion=50M -XX:MinMetaspaceFreeRatio=5

以後修改MinMetaspaceFreeRatio的爲20,35,50,65分別能夠獲得以下的GC數據

5
2015-07-05T20:47:47.444+0800: ... [Metaspace: 13580K->13580K(51200K)]...
2015-07-05T20:47:47.741+0800: ... [Metaspace: 24981K->24981K(102400K)]...
2015-07-05T20:47:48.150+0800: ... [Metaspace: 36381K->36381K(153600K)]...
2015-07-05T20:47:48.584+0800: ... [Metaspace: 47781K->47781K(204800K)]...
2015-07-05T20:47:49.124+0800: ... [Metaspace: 59182K->59182K(256000K)]...
2015-07-05T20:47:49.717+0800: ... [Metaspace: 70582K->70582K(307200K)]...
2015-07-05T20:47:50.462+0800: ... [Metaspace: 81982K->81982K(358400K)]...
2015-07-05T20:47:51.278+0800: ... [Metaspace: 93382K->93382K(409600K)]...
2015-07-05T20:47:52.272+0800: ... [Metaspace: 104782K->104782K(460800K)]...
2015-07-05T20:47:53.418+0800: ... [Metaspace: 116182K->116182K(512000K)]...
20
2015-07-05T20:50:16.123+0800: ... [Metaspace: 13580K->13580K(51200K)]...
2015-07-05T20:50:16.404+0800: ... [Metaspace: 24981K->24981K(102400K)]...
2015-07-05T20:50:16.754+0800: ... [Metaspace: 36381K->36381K(153600K)]...
2015-07-05T20:50:17.234+0800: ... [Metaspace: 47781K->47781K(204800K)]...
2015-07-05T20:50:17.758+0800: ... [Metaspace: 59182K->59182K(256000K)]...
2015-07-05T20:50:18.499+0800: ... [Metaspace: 73432K->73432K(321536K)]...
2015-07-05T20:50:19.591+0800: ... [Metaspace: 91244K->91244K(401408K)]...
2015-07-05T20:50:21.326+0800: ... [Metaspace: 113510K->113510K(501760K)]...
2015-07-05T20:50:21.868+0800: ... [Metaspace: 116182K->116182K(512000K)]...
35
2015-07-05T20:56:02.338+0800: ... [Metaspace: 13581K->13581K(51200K)]...
2015-07-05T20:56:02.619+0800: ... [Metaspace: 24981K->24981K(102400K)]...
2015-07-05T20:56:03.010+0800: ... [Metaspace: 37258K->37258K(157696K)]...
2015-07-05T20:56:03.733+0800: ... [Metaspace: 56146K->56146K(243712K)]...
2015-07-05T20:56:05.233+0800: ... [Metaspace: 85206K->85206K(374784K)]... 
2015-07-05T20:56:07.548+0800: ... [Metaspace: 116182K->116182K(512000K)]...
50
2015-07-05T20:59:08.866+0800: ... [Metaspace: 13580K->13580K(51200K)]...
2015-07-05T20:59:09.153+0800: ... [Metaspace: 24981K->24981K(102400K)]...
2015-07-05T20:59:09.863+0800: ... [Metaspace: 47781K->47781K(204800K)]...
2015-07-05T20:59:12.178+0800: ... [Metaspace: 93382K->93382K(409600K)]...
2015-07-05T20:59:14.031+0800: ... [Metaspace: 116182K->116182K(512000K)]...
65
2015-07-05T21:01:03.353+0800: ... [Metaspace: 13581K->13581K(51200K)]...
2015-07-05T21:01:03.888+0800: ... [Metaspace: 34753K->34753K(147456K)]...
2015-07-05T21:01:06.648+0800: ... [Metaspace: 95245K->95245K(419840K)]...
2015-07-05T21:01:08.547+0800: ... [Metaspace: 116182K->116182K(512000K)]...

從上面的數據能夠看出 
- 隨着-XX:MinMetaspaceFreeRatio的不斷增長,在到達設定的Max以前所經歷的GC次數也就越少 
- 隨着-XX:MinMetaspaceFreeRatio的不斷增長,平均下來每一次GC後對應的MetaSpaceSize相對於以前的增加幅度都會增長。好比在-XX:MinMetaspaceFreeRatio爲5的時候,每次增加還基本上維持在設置的增加最小值(-XX:MinMetaspaceExpansion)50MB,而增加到65的時候,每次增加都在200MB以上。這彷佛能夠說明-XX:MinMetaspaceFreeRatio越大,JVM越認爲須要快速的增加MetaSpaceSize以防止頻繁的進行的進行GC 
- -XX:MinMetaspaceFreeRatio設定的太小,會影響內存增加,致使比較頻繁的GC。而過大怎會致使內存單次增加過多,形成沒必要要的浪費。默認的40是一個比較好的選擇。

參考資料

http://www.slideshare.net/TakahiroYamada3/tools-for-metaspace 
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html 
http://itdoc.hitachi.co.jp/manuals/link/has_v101001/0344211De/metaspacesize.htm 
https://blogs.oracle.com/poonam/entry/about_g1_garbage_collector_permanent 
http://itdoc.hitachi.co.jp/manuals/link/has_v101001/0344211De/compressedclassspacesize.htm 
http://stackoverflow.com/questions/30511439/java-lang-outofmemoryerror-compressed-class-space 
http://it.deepinmind.com/gc/2014/05/14/metaspace-in-java-8.html

相關文章
相關標籤/搜索