个人的sts.ini方案以及后面的详细说明
-startup
plugins/org.eclipse.equinox.launcher_1.5.400.v20190515-0925.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.1000.v20190125-2016
-product
org.springsource.sts.ide
--launcher.defaultAction
openFile
#JVM路径
-vm
D:\Java\jdk\jdk1.8.0_221\jre\bin\server\jvm.dll
#JVM参数设置
-vmargs
-Dosgi.requiredJavaVersion=1.8
--add-modules=ALL-SYSTEM
-Dosgi.module.lock.timeout=10
-Dorg.eclipse.swt.browser.IEVersion=10001
#JVMGC详情输出
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:D:\Java\jdk\gclog\gc.log
#一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小
#初始堆内存
-Xms2048m
#最大堆内存
-Xmx2048m
#年轻代堆内存
-Xmn1536m
#元空间初始大小
-XX:MetaspaceSize=128m
#最大元空间大小
-XX:MaxMetaspaceSize=1024m
#取消字节码校验,加快JVM类加载
-Xverify:none
#方法调用100次会被编译成本地机器码
-XX:CompileThreshold=100
#使用并发内存回收
-XX:+UseParallelGC
#禁止RMI(Java远程方法调用)调用System.gc,因为System.gc可能会触发FULL GC
-XX:+DisableExplicitGC
#配置并行收集器的线程数
-XX:ParallelGCThreads=4
1.使用-vm参数设置JVM路径
-vm
D:\Java\jdk\jdk1.8.0_221\jre\bin\server\jvm.dll
2.调整JVM堆内存以及元空间大小
首先将JVM的GC详情输出到日志中:
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:D:\Java\jdk\gclog\gc.log
查看GC日志。
2019-08-12T09:42:00.092+0800: 3.176: [GC (Metadata GC Threshold) [PSYoungGen: 754975K->54895K(1376256K)] 754975K->55119K(1900544K), 0.0484245 secs] [Times: user=0.25 sys=0.02, real=0.05 secs]
2019-08-12T09:42:00.140+0800: 3.225: [Full GC (Metadata GC Threshold) [PSYoungGen: 54895K->0K(1376256K)] [ParOldGen: 224K->53437K(524288K)] 55119K->53437K(1900544K), [Metaspace: 18797K->18797K(1069056K)], 0.1167065 secs] [Times: user=0.58 sys=0.02, real=0.12 secs]
2019-08-12T09:42:01.958+0800: 5.042: [GC (Metadata GC Threshold) [PSYoungGen: 419142K->28800K(1376256K)] 472579K->82246K(1900544K), 0.0269177 secs] [Times: user=0.14 sys=0.00, real=0.03 secs]
2019-08-12T09:42:01.985+0800: 5.069: [Full GC (Metadata GC Threshold) [PSYoungGen: 28800K->0K(1376256K)] [ParOldGen: 53445K->61105K(524288K)] 82246K->61105K(1900544K), [Metaspace: 31810K->31810K(1079296K)], 0.0913621 secs] [Times: user=0.38 sys=0.02, real=0.09 secs]
2019-08-12T09:42:08.064+0800: 11.148: [GC (Metadata GC Threshold) [PSYoungGen: 718732K->42937K(1376256K)] 779838K->104051K(1900544K), 0.0254809 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]
2019-08-12T09:42:08.089+0800: 11.174: [Full GC (Metadata GC Threshold) [PSYoungGen: 42937K->0K(1376256K)] [ParOldGen: 61113K->94403K(524288K)] 104051K->94403K(1900544K), [Metaspace: 52351K->52351K(1099776K)], 0.4184534 secs] [Times: user=1.30 sys=0.00, real=0.42 secs]
2019-08-12T09:42:15.203+0800: 18.286: [GC (Allocation Failure) [PSYoungGen: 1179648K->42136K(1376256K)] 1274051K->136548K(1900544K), 0.0419592 secs] [Times: user=0.09 sys=0.00, real=0.04 secs]
2019-08-12T09:42:15.862+0800: 18.946: [GC (Metadata GC Threshold) [PSYoungGen: 243269K->31185K(1376256K)] 337681K->125605K(1900544K), 0.0245842 secs] [Times: user=0.13 sys=0.00, real=0.03 secs]
2019-08-12T09:42:15.887+0800: 18.971: [Full GC (Metadata GC Threshold) [PSYoungGen: 31185K->0K(1376256K)] [ParOldGen: 94419K->107256K(524288K)] 125605K->107256K(1900544K), [Metaspace: 88351K->88348K(1134592K)], 0.2870267 secs] [Times: user=0.88 sys=0.00, real=0.29 secs]
我们应该如何去分析GC日志呢?
2019-08-12T09:42:01.985+0800(当前时间戳): 5.069: [Full GC(GC类型) (Metadata GC Threshold(发生GC的原因)) [PSYoungGen(年轻代回收): 28800K(年轻代回收前的大小)->0K(年轻代回收后的大小)(1376256K)(年轻代总大小)] [ParOldGen(老年代回收): 53445K(老年代回收前的大小)->61105K(老年代回收后的大小)(524288K)(老年代总大小)] 82246K(堆内存回收前大小)->61105K(堆内存回收后大小)(1900544K(堆内存总大小)), [Metaspace(元空间回收): 31810K(元空间回收前大小)->31810K(元空间回收后大小)(1079296K)(元空间总大小)], 0.0913621 secs(回收时间)] [Times: user=0.38(用户耗时) sys=0.02(系统耗时), real=0.09 (实际耗时)secs]
调试的原则:避免JVM中的FULL GC的发生,因为FULL GC会引起老年代的垃圾回收,而老年代的垃圾回收耗时耗力。同时根据电脑的内存适当增加堆内存的大小。调整后各区域内存大小:
#初始堆内存
-Xms2048m
#最大堆内存
-Xmx2048m
#年轻代
-Xmn1536m
#元空间
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=1024m
注:JDK 1.8 JVM结构发生改变,元空间(Metaspace)取代永久代(PermGen)。因此JDK1.8之前应该调整永久代的大小,而JDK1.8以后调整元空间的大小。
JDK1.8之前版本参数优化举例:
-Xms2048m
-Xmx2048m
-Xmn1536m
#永久代
-XX:PermSize=128m
-XX:MaxPermSize=1024m
3.关闭字节码校验
#取消字节码校验,加快JVM类加载
-Xverify:none
4.配置并行垃圾回收
#使用并发内存回收
-XX:+UseParallelGC
#配置并行收集器的线程数
-XX:ParallelGCThreads=4
5.禁止代码中显示调用GC
#禁止RMI(Java远程方法调用)调用System.gc,因为System.gc可能会触发FULL GC
-XX:+DisableExplicitGC
注:NIO直接内存的回收,需要依赖于System.gc()。如果我们的应用中使用了java nio中的direct memory,那么使用-XX:+DisableExplicitGC要小心,存在潜在的内存泄露风险。
6.确定编译器阈值,控制编译的条件
#方法调用100次会被编译成本地机器码
-XX:CompileThreshold=100