常用的参数
-Xmn:年轻代大小 -Xms:堆初始大小 -Xmx:堆最大大小 -Xss:栈大小
需要注意,因为有堆外内存,分配内存不要全分配掉,可使用-XX:MaxDirectMemorySize=10M控制堆外内存的大小。超过此内存则会报错。
-XX:+UseTlab:使用tlab,默认打开,涉及到对象分配问题
-XX:+PrintTlab:打印tlab使用情况
-XX:+TlabSize:设置Tlab大小
-XX:+DisabledExplictGC:java代码中的System.gc()不再生效,防止代码中误写,导致频繁触动GC,默认不起用。
-XX:+PrintGC(+PrintGCDetails/+PrintGCTimeStamps)打印GC信息(打印GC详细信息/打印GC执行时间)
-XX:+PrintHeapAtGC打印GC时的堆信息
-XX:+PrintGCApplicationConcurrentTime 打印应用程序的时间
-XX:+PrintGCApplicationStopedTime 打印应用程序暂停时间
-XX:+PrintReferenceGC 打印回收多少种引用类型的引用
-verboss:class 类加载详细过程
-XX:+PrintVMOptions 打印JVM运行参数
-XX:+PrintFlagsFinal(+PrintFlagsInitial) -version | grep 查找想要了解的命令,很重要
-X:loggc:/opt/gc/log/path 输出gc信息到文件
-XX:MaxTenuringThreshold 设置gc升到年龄,最大值为15
常见的垃圾回收器
java8常用的,基本就是Serial、Parallel、CMS、G1等
1、Serial
垃圾收集器的原始实现,使用单线程。当垃圾收集器运行时,会停止应用程序。适用于能够承受短暂停顿的应用程序。该垃圾收集器占用内存空间比较小,因此这是嵌入式应用程序的首选垃圾收集器类型。在运行时使用以下命令启用该垃圾收集器:
-XX:+UseSerialGC
2、Parallel
像 Serial 收集器一样,Parallel 收集器也使用“stop the world”方法。这意味着,当垃圾收集器运行时,应用程序线程会停止。但是不同的是,Parallel 收集器运行时有多个线程执行垃圾收集操作。这种类型的垃圾收集器适用于在多线程和多处理器环境中运行中到大型数据集的应用程序。
Parallel 主要有两个版本,-XX:+UseParallelGC
使用这个命令,指定在新生代中通过多个线程进行垃圾回收,而老年代中的垃圾收集和内存压缩仍使用单个线程完成的。-XX:+UseParallelOldGC
,它对新生代和老年代都使用多线程。
使用该垃圾收集器时可以通过使用各种合适的 JVM 参数进行调优,例如内存大小,吞吐量、暂停时间、线程数和内存占用。如下:
- 线程数:
-XX:ParallelGCThreads=<N>
- 暂停时间:
-XX:MaxGCPauseMillis=<N>
- 吞吐量(垃圾收集花费的时间与实际应用程序执行的时间相比):
-XX:GCTimeRatio=<N>
- 最大堆内存:
-Xmx<N>
3、CMS(Concurrent Mark Sweep)慎选
(CMS)垃圾收集器与应用程序并行运行。对于新生代和老年代都使用了多线程。在 CMS 垃圾收集器删除无用对象后,不会对存活对象进行内存压缩。该垃圾收集器和应用程序并行运行,会降低应用程序的响应时间,适用于停顿时间较短的应用程序。这个收集器在 Java8 已过时,并在 Java14 中被移除。
-XX:+UseConcMarkSweepGC
在 CMS 使用过程中,应用程序将暂停两次。首次暂停发生在标记可直接访问的存活对象时,这个暂停被称为初始标记。第二次暂停发生在 CMS 收集器结束时期,来修正在并发标记过程中,应用程序线程在 CMS 垃圾回收完成后更新对象时被遗漏的对象。这就是重新标记。
4、G1 收集器
G1 垃圾收集器旨在替代 CMS。G1 垃圾收集器具备并行、并发以及增量压缩,且暂停时间较短。G1 收集器将堆内存划分为大小相同的区域,通过多个线程触发全局标记阶段。标记阶段完成后,G1 知道哪个区域可能大部分是空的,并首选该区域作为清除/删除阶段。
在 G1 收集器中,一个对象如果大小超过半个区域容量会被认为是一个“大对象” 。这些对象被放置在老年代中“humongous region”的区域中。
-XX:+UseG1GC
5、Shenandoah (JDK12)
Shenandoah 是在 JDK12 中引入的,是一种 CPU 密集型垃圾收集器。它会进行内存压缩,立即删除无用对象并释放操作系统的空间。所有的这一切与应用程序线程并行发生。启用命令如下:
-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
6、ZGC (JDK15)
ZGC 为低延迟需要和大量堆空间使用而设计,允许当垃圾回收器运行时 Java 应用程序继续运行。它是基于动态Region内存布局,(暂时)不设年龄分代,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-整理算法的收集器。ZGC 收集器在 JDK11 引入,在 JDK15,ZGC 和 Shenandoah 成熟。
当然,新的不代表是最好的,它也在存在问题,就是它的浮动垃圾。目前唯一的办法是增大堆的容量,使得程序得到更多的喘息时间。明显治标不治本,根本原因还是它没有进行一个年龄分代,对新生代没有进行更快Minor GC。所以解决方法,还是分代
启用 ZGC 收集器使用如下命令:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
我的项目用的是jdk17,用的就是ZGC,直接给大家一个详细的配置注释
##使用ZGC 可伸缩的超低延迟垃圾回收器
JAVA_OPTS="$JAVA_OPTS -XX:+UseZGC "
##GC并发线程数和 并行执行线程数
JAVA_OPTS="$JAVA_OPTS -XX:ConcGCThreads=2 -XX:ParallelGCThreads=6 "
##ZCollectionInterval ZGC发生的最小时间间隔,单位秒 ZAllocationSpikeTolerance ZGC触发自适应算法的修正系数,默认2,数值越大,越早的触发ZGC
JAVA_OPTS="$JAVA_OPTS -XX:ZCollectionInterval=120 -XX:ZAllocationSpikeTolerance=5 "
#是否启用主动回收,默认开启
JAVA_OPTS="$JAVA_OPTS -XX:+UnlockDiagnosticVMOptions -XX:-ZProactive "
#设置GC日志中的内容、格式、位置以及每个日志的大小
JAVA_OPTS="$JAVA_OPTS -Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=log/gc/gc-%t.log:time,tid,tags:filecount=5,filesize=50m "