垃圾回收-实战篇

作者:微信小助手

发布时间:2020-03-02T13:59:20

上文 GC 理论颇受大家好评,学习了之后,相信大家对 GC 的工作原理有了比较深刻的认识,这一篇我们继续趁热打铁,来学习下 GC 的实战内容,主要包括以下几点

  • JVM 参数简介

  • 发生 OOM 的主要几种场景及相应解决方案

  • OOM 问题排查的一些常用工具

  • GC 日志格式怎么看

  • jstat 与可视化 APM 工具构建

  • 再谈 JVM 参数设置

JVM 参数简介

在开始实践之前我们有必要先简单了解一下 JVM 参数配置,因为本文之后的实验中提到的 JVM 中的栈,堆大小,使用的垃圾收集器等都需要通过 JVM 参数来设置

先来看下如何运行一个 Java 程序

public class Test {
    public static  void main(String[] args) {
        System.out.println("test");
    }
}
  1. 首先我们通过 javac Test.java 将其转成字节码

  2. 其次我们往往会输入 java Test 这样的命令来启动 JVM 进程来执行此程序,其实我们在启动 JVM 进程的时候,可以指定相应的 JVM 的参数,如下蓝色部分

指定这些 JVM 参数我们就可以指定启动 JVM 进程以哪种模式(server 或 client),运行时分配的堆大小,栈大小,用什么垃圾收集器等等,JVM 参数主要分以下三类

1、 标准参数(-),所有的 JVM 实现都必须实现这些参数的功能,而且向后兼容;例如 -verbose:gc(输出每次GC的相关情况)

2、 非标准参数(-X),默认 JVM 实现这些参数的功能,但是并不保证所有 JVM 实现都满足,且不保证向后兼容,栈,堆大小的设置都是通过这个参数来配置的,用得最多的如下

参数示例 表示意义
-Xms512m JVM 启动时设置的初始堆大小为 512M
-Xmx512m JVM 可分配的最大堆大小为 512M
-Xmn200m 设置的年轻代大小为 200M
-Xss128k 设置每个线程的栈大小为 128k

3、非Stable参数(-XX),此类参数各个 jvm 实现会有所不同,将来可能会随时取消,需要慎重使用, -XX:-option 代表关闭 option 参数,-XX:+option 代表要关闭 option 参数,例如要启用串行 GC,对应的 JVM 参数即为 -XX:+UseSerialGC。非 Stable 参数主要有三大类

  • 行为参数(Behavioral Options):用于改变 JVM 的一些基础行为,如启用串行/并行 GC

参数示例 表示意义
-XX:-DisableExplicitGC 禁止调用System.gc();但jvm的gc仍然有效
-XX:-UseConcMarkSweepGC 对老生代采用并发标记交换算法进行GC
-XX:-UseParallelGC 启用并行GC
-XX:-UseParallelOldGC 对Full GC启用并行,当-XX:-UseParallelGC启用时该项自动启用
-XX:-UseSerialGC 启用串行GC
  • 性能调优(Performance Tuning):用于 jvm 的性能调优,如设置新老生代内存容量比例

参数示例 表示意义
-XX:MaxHeapFreeRatio=70 GC后java堆中空闲量占的最大比例
-XX:NewRatio=2 新生代内存容量与老生代内存容量的比例
-XX:NewSize=2.125m 新生代对象生成时占用内存的默认值
-XX:ReservedCodeCacheSize=32m 保留代码占用的内存容量
-XX:ThreadStackSize=512 设置线程栈大小,若为0则使用系统默认值
  • 调试参数(Debugging Options):一般用于打开跟踪、打印、输出等 JVM 参数,用于显示 JVM 更加详细的信息

参数示例 表示意义
-XX:HeapDumpPath=./java_pid .hprof 指定导出堆信息时的路径或文件名
-XX:-HeapDumpOnOutOfMemoryError 当首次遭遇OOM时导出此时堆中相关信息
-XX:-PrintGC 每次GC时打印相关信息
-XX:-PrintGC Details 每次GC时打印详细信息

画外音:以上只是列出了比较常用的 JVM 参数,更多的 JVM 参数介绍请查看文末的参考资料

明白了 JVM 参数是干啥用的,接下来我们进入实战演练,下文中所有程序运行时对应的 JVM 参数都以 VM Args 的形式写在开头的注释里,读者如果在执行程序时记得要把这些 JVM 参数给带上哦