JVM系列(十) 垃圾收集器之 Parallel Scavenge/Old

2023-11-03

上篇文章我们讲解了单线程垃圾收集器 Serial/SerialOld ,与之相对应的多线程垃圾收集器就是 Parallel Scavenge/Old, 本文我们讲解下多线程垃圾收集器 Parallel Scavenge/Old

垃圾收集器
  • 新生代收集器: Serial、ParNew、Parallel Scavenge;
  • 老年代收集器: Serial Old、CMS、Parallel Old;
  • 通用收集器: G1;

收集器常用组合:

  1. Serial + Serial Old
  2. Parallel Scavenge + Parallel Old
  3. ParNew + CMS配合
  4. G1(不需要组合其他收集器)

今天我们要讲的就是 Parallel Scavenge/Old收集器,它采用了复制算法、并行回收、“Stop-the-World”机制,与ParNew对比

  • Parallel Scavenge称为吞吐量优先的垃圾收集器,收集器的目标则是达到一个可控制的吞吐量
  • 自适应调节策略也是Parallel Scavenge 与ParNew一个重要区别。

Parallel Old 收集器采用了标记-压缩算法,但同样也是基于并行回收和“Stop-the-World”机制、

1.Parallel Scavenge/Old Java8 默认垃圾收集器

查看你自己的jdk使用的默认垃圾收集器,如果你是java8,而且没有在项目中指定垃圾收集器,那么他就是ParallelGC 并行垃圾收集器

#查看jdk版本 使用的默认垃圾收集器使用的默认垃圾收集器
java -XX:+PrintCommandLineFlags -version

打印日志,XX:+UseParallelGC 默认是采用的多线程垃圾收集器

C:\Users\jzj>java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=265507840 -XX:MaxHeapSize=4248125440 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)使用的默认垃圾收集器
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
2.JVM参数设置
  • -XX:+UserParallelGC :手动指定年轻代使用Parallel 并行收集器执行内存回收任务。

  • -XX:+UserParallelOldGC :手动指定老年代都是使用并行回收收集器。

    • 分别适用于新生代和老年代。默认jdk8是开启的。
    • 上面两个参数,默认开启一个,另一个也会被开启。二者相互激活
  • -XX:ParallelGCThreads 设置年轻代并行收集器的线程数

    • 最好与CPU数量相等,以避免过多的线程数影响垃圾收集性能。
    • 默认情况下,当CPU数量小于8个,ParallelGCThreads的值等于CPU数量。
    • 当CPU数量大于8个,ParallelGCThreads的值等于8 + (ncpus - 8 ) ( 5/8 )
    • 在无特殊要求下,ParallelGCThreads参数使用默认值就可以了。
    • 在JRE版本1.8.0_131之前,JVM无法感知Docker的CPU限制,会使用宿主机的逻辑核数计算默认值,如部署在128核物理机上的容器,JVM中默认ParallelGCThreads为83,远超过了容器的核数
    • 导致过多的GC线程数抢占了业务线程的CPU时间,加上线程切换的开销,较大的降低了吞吐量
    • 推荐升级1.8.0_192
  • -XX:MaxGCPauseMillis 设置垃圾收集器最大停顿时间(即STW的时间)。单位是毫秒。

    • 停顿时间越短体验越好,但是在服务器端,我们注重高并发,整体的吞吐量,所以服务器端适合Parallel,进行控制。
  • -XX:GCTimeRatio 垃圾收集时间占总时间的比例(=1/(N+1))

    • 用于衡量吞吐量的大小。取值范围(0,100).默认值是99,也就是垃圾收集时间不超过1%.
  • -XX:+UserAdaptiveSizePolicy 设置Parallel Scavenge 收集器具有自适应调节策略。

    • 在这种模式下,年轻代的大小、Eden和Survivor的比例、晋升老年代的对象年龄等参数会被自动调整
    • 自动调整从而达到堆大小,吞吐量和停顿时间的平衡点。

在手动调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆大小,目标吞吐量(GCTimeRatio)和停顿时间(MaxGCPauseMills),让虚拟机自己完成调优工作。

3.测试GC日志

设置JVM参数,注意注意注意 我这里是没有设置使用何种GC回收方式的,采用的就是默认的 使用的默认垃圾收集器UseParallelGC

-verbose:gc -Xms10M -Xmx10M  -XX:+PrintGC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:SurvivorRatio=8

image.png
默认使用 UseParallelGC

  • 年轻代 PSYoungGen
  • 伊甸区 eden
  • Surviral from区 from
  • Surviral to区 to
  • 老年代 ParOldGen
  • 元空间 Metaspace
3.1 JVM测试类

Jvm测试类,设置JVM最大堆10M, for循环10次,每次增加1M的内存

package com.jzj.jvmtest.jvmready;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ParallelTest {

    //JVM 参数 -verbose:gc -Xms10M -Xmx10M  -XX:+PrintGC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:SurvivorRatio=8
    public static void main(String[] args) throws Exception {
        byte[] b = null;
        for (int i = 1; i <= 10; i++) {
            //设置 1M的对象
            log.info("======== " + i + "次添加1M对象");
            b = new byte[1 * 1024 * 1024];
            Thread.sleep(100);
        }
    }
}

打印GC日志

[GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->836K(9728K), 0.0008089 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2552K->512K(2560K)] 2884K->1202K(9728K), 0.0008076 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2541K->512K(2560K)] 3232K->1687K(9728K), 0.0009372 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
23:58:24.981 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 1次添加1M对象
23:58:25.090 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 2次添加1M对象
23:58:25.201 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 3次添加1M对象
23:58:25.312 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 4次添加1M对象
23:58:25.423 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 5次添加1M对象
23:58:25.531 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 6次添加1M对象
23:58:25.642 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 7次添加1M对象
[GC (Allocation Failure) [PSYoungGen: 2252K->496K(2560K)] 8547K->6976K(9728K), 0.0007743 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
23:58:25.751 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 8次添加1M对象
[GC (Allocation Failure) --[PSYoungGen: 1559K->1559K(2560K)] 8040K->8088K(9728K), 0.0009963 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 1559K->0K(2560K)] [ParOldGen: 6528K->2581K(7168K)] 8088K->2581K(9728K), [Metaspace: 5077K->5077K(1056768K)], 0.0046449 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
23:58:25.860 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 9次添加1M对象
23:58:25.970 [main] INFO com.jzj.jvmtest.jvmready.ParallelTest - ======== 10次添加1M对象
Heap
 PSYoungGen      total 2560K, used 1506K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 73% used [0x00000000ffd00000,0x00000000ffe78990,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 7168K, used 4629K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 64% used [0x00000000ff600000,0x00000000ffa857f0,0x00000000ffd00000)
 Metaspace       used 5179K, capacity 5308K, committed 5504K, reserved 1056768K
  class space    used 574K, capacity 596K, committed 640K, reserved 1048576K
3.2 GC日志分析
GC日志参数 含义
GC (Allocation Failure) GC引起原因是年轻代没有足够空间存储新数据
Full GC (Ergonomics) FullGC引起原因是老年代空间不足,gc垃圾回收后依旧存在大量对象
PSYoungGen 新生代,这个名称由收集器决定。PS是Parallel Scavenge收集器的缩写
ParOldGen Parallel Scavenge收集器配套的老年代
Metaspace Parallel Scavenge收集器配套的永久代
total & used 总的空间和用掉的空间

对GC日志进行分析

首先看下YoungGC

  • GC (Allocation Failure) 内存分配失败,发生YoungGC
  • PSYoungGen: 2048K->504K(2560K)] 2048K->844K(9728K), 0.0010931 secs 发生YGC,YGC前,新生代已使用2048K->gc发生后内存使用504K, 2560K是新生代区域总容量
    • 换句话说就是 新生代回收前已使用 2048
    • YGC回收后,新生代已使用504k
    • YGC释放了多少内存,回收了多少垃圾? 2048-504 = 1544K的空间
    • 新生代总大小为 2560K
  • 2048K->836K(9728K) 表示YGC前 Java堆已使用容量2048K, YGC发生后Java堆使用了836K,Java的总的可用的堆容量为9728K
    • 于Java堆来说 YGC释放了2048-836 = 1212K 的空间
  • 0.0010931 secs YGC回收垃圾耗时
  • Times: user=0.00 sys=0.00, real=0.00 secs
    • 用户消耗cpu时间, 内核态消耗cpu时间, 真正操作消耗的时间

下面我们看下FullGC

Full GC (Ergonomics) 发生FullGC,清除所有区域的垃圾对象,发生了STW(Stop The World)

  • PSYoungGen: 1551K->0K(2560K) 年轻代 gc前占用 1551K-> gc后 0K,年轻代对象全部被销毁,年轻代大小2560K
  • ParOldGen: 6558K->2640K(7168K)] 老年代 gc前占用 6558K ->gc后 2640K,老年代也销毁了一部分,老年代大小7168K
  • 8110K->2640K(9728K) Java堆大小 gc前占用 8110K ->gc后 2640K, 年轻代剩余0K+老年代剩余2640K 就是Java堆gc后的剩余 2640K, Java堆总大小 9782K
  • Metaspace: 5084K->5084K(1056768K)], 0.0040923 secs] 元空间及该次FullGc消耗时间

这就是 ParallelGC 垃圾收集器的处理方式及GC的日志分析,我们可以通过GC日志看到新生代及老年代的存活对象情况,适当的调整参数,达到最完美的JVM状态

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM系列(十) 垃圾收集器之 Parallel Scavenge/Old 的相关文章

  • Eclipse 中的 Java 简单电子邮件程序

    我想制作一个简单的程序 您可以从其中发送电子邮件命令行 我找到了这个教程 http www tutorialspoint com java java sending email htm http www tutorialspoint com
  • Java简单加密

    我想加密存储在磁盘上的文本 配置 文件 尝试使用DES http en wikipedia org wiki Data Encryption Standard加密 我在客户端计算机上遇到了致命错误 后来我发现该算法无法处理重音字符 我怀疑这
  • 在游戏框架中编写功能测试的正确方法

    在为基于 play1 2 4 的 web 应用程序编写功能测试时 我对如何正确编码感到有点困惑 困惑在于所涉及的事务边界 我在某处读到每个测试都有自己的事务 在我的应用程序中 用户可以登录并向购物车添加一些商品 然后他可以提供一个地址 以便
  • 如何在 Android 中恢复我的音频?

    我必须实现用于创建具有暂停和恢复状态的音频的应用程序 当我的应用程序作为启动时音频启动 当我按下模拟器上的后退按钮时 音频音乐处于暂停状态 但是当我的活动回来时从停止状态到前台我的音频音乐未恢复 这是我的代码 public class Au
  • Spring MVC 中的 CSRF(跨站请求伪造)保护

    我对春季的 CSRF 跨站请求伪造 保护有点困惑 不 我有我的 jsp 我的控制器和一个 Web 服务 我想要做的是在 Web 服务级别验证令牌 如果令牌匹配 则运行 Web 服务 在我的例子中执行数据库插入 JSP file
  • Java:BufferedInputStream 的 available() 方法存在问题

    我正在处理以下代码 用于将大文件拆分为一组较小的文件 FileInputStream input new FileInputStream this fileToSplit BufferedInputStream iBuff new Buff
  • 平衡括号问题的优化解

    给定一个仅包含字符的字符串 and 判断输入字符串是否有效 输入字符串在以下情况下有效 左括号必须由相同类型的括号封闭 左括号必须按正确的顺序关闭 请注意 空字符串也被视为有效 示例1 Input Output true Example 2
  • Eclipse 内容协助无法在枚举常量参数列表中工作

    使用 eclipse 当我输入以下内容时 public enum Foo A Integer private final Integer integer private Foo Integer integer this integer in
  • Hibernate、MySQL 视图和 hibernate.hbm2ddl.auto = 验证

    我可以在 Hibernate 中使用 MySQL 视图 将它们视为表 即 该实体与为表创建的实体没有什么不同 但是 当 Hibernate 设置为验证模型时 我的应用程序将不会部署 因为它找不到视图 因为它假设它是一个表 是否可以在启用部署
  • 从另一个类添加 Swing 组件

    我正在学习java 我正在尝试从另一个类向我的框架添加一个菜单栏 练习将代码划分为多个类以更好地组织程序 这是我的代码示例 public class MainApp public static void main String args C
  • 更改 Spring Web 应用程序的默认会话超时

    我必须测试一个由 spring 和 jsp 编写的 Web 应用程序 应用程序的默认会话超时为 30 分钟 我想减少会话超时 为此 我改变了web xml文件输入tomcatInstallationLocation conf 但这不起作用
  • 如何在Android中使用资源

    一个人如何使用资产 我有这个代码 AssetManager assets getAssets InputStream stream assets open test txt 看起来它只能在 Activity 类中使 用 如果我尝试在另一个类
  • 无法从 ViewPager 中的 Fragment 编辑 ActionBar 标题

    我有一个Activity它通过一个托管多个片段ViewPager 在活动的onCreate方法我使用以下代码来更改ActionBar title Toolbar toolbar findViewById R id toolbar setSu
  • 不想保留一对一的实体

    假设我有两节课Employee and Department In Employee我已经写了 OneToOne fetch FetchType EAGER cascade CascadeType ALL JoinColumn name d
  • 为什么 Cassandra 客户端在生产中没有 epoll 时会失败? [复制]

    这个问题在这里已经有答案了 当我在本地运行服务时 我收到一条警告 指出 epoll 不可用 因此它使用 NIO 很公平 当我将其部署到 Kubernetes 中时 我得到了以下信息 这导致服务无法运行 2017 03 29T19 09 22
  • APACHE POI 从 Java 中的 Excel 获取精确的字体颜色

    在 Excel 工作表中 如何使用 Java 中的 Apache POI 获取准确的字体颜色值 我试图通过使用来获取字体颜色 org apache poi ss usermodel Font f book getFontAt style g
  • 使用泛型进行选择排序

    我对整数进行了选择排序并且它正在工作 当我尝试修改程序以使用泛型时 编译器会抱怨 我不知道如何修复它 如果有人能提出一些建议和建设性意见 我将不胜感激 这是代码 public class SelelctionSort public stat
  • C3P0:生产中未返回的连接超时?

    参数unreturnedConnectionTimeout给定时间段后未返回的连接超时 我正在尝试决定是否应该在我的制作中使用它persistence xml 使用它的一大优点是连接池将能够从泄漏的连接中恢复 一个很大的缺点是泄漏的连接将很
  • org.apache.catalina.core.JreMemoryLeakPreventionListener 中急切调用 URLConnection 的 setDefaultUseCaches(false) 是什么原因

    这个问题可能有点难以找到答案 这是一个系列中的问题考虑使用 Policy getPolicy 的原因是什么 因为它将保留对上下文的静态引用并可能导致内存泄漏 https stackoverflow com questions 7057421
  • 丰富:数据表行跨度问题

    我需要创建一个 rich dataTable 甚至扩展 具有以下功能 我有一个公司类 其中包含产品对象的集合 我想展示下表 我仍然没有弄清楚如何使用子表执行此操作 在所有示例中 我发现子表具有与主表完全相同的列 据推测 我需要在前两列中使用

随机推荐

  • 两个有序数组合并成一个有序数组——C++实现

    程序分析 这里做的是升序 C 代码 include
  • 如何监控Android模拟器的HTTP访问情况

    前几个月 在调试某个应用时 需要监控应用与服务器之间的HTTP通讯 从搜索引擎找到的方案几乎全错 要么是人云亦云 要么是只能满足旧的平台版本 要么根本就是臆测 不得其解之际 用比较复杂的方法解决了 昨天想起来 觉得太过窝囊 于是重整旗鼓 终
  • react-节点更新与销毁

    文章目录 更新与销毁 节点更新 对比更新 找到了对比目标 没有找到对比目标 更新与销毁 发生更新的场景 重新调用ReactDOM render 触发根节点更新 在类组件中调用setState 会导致该节点更新 节点更新 分为两种 如果调用的
  • Linux学习命令

    cd ls mkdir rmdir rm touch 创建文件 cat 显示文件内容 不适合查看内容较长的文件 n 显示行号 cat n etc issue tac 和cat类似 但是是倒过来显示 more 分页显示文件内容 空格 或f 翻
  • 【CLYZ集训】马可波罗【按位】【博弈论】

    题目大意 有两个人 n n n堆石子 每个人轮流取 每次可以取1 x x x个 最后没得取的人输 两人都采取最优策略 问对于 x
  • 双目视觉标定MATLAB

    双目标定 双目摄像机需要标定的参数 摄像机内参数矩阵 畸变系数 两相机之间的旋转矩阵 R 和平移矩阵 T 其中摄像机内参数矩阵和畸变系数矩阵可以通过单目标定的方法标定出来 双目摄像机标定和单目摄像机标定最主要的区别就是双目摄像机需要标定出左
  • oracle自定义函数function

    遇到的问题 遇到一个数据统计的需求 要求 统计身份证号码性别位填写错误的个数 首先普及身份证性别位 至今为止身份证有18位和15位两种 18位身份证号性别位是17位 第17位数字奇数为男性 偶数为女性 0也是女性 15位身份证号性别位是最后
  • springboot AOP日志

    引入项目依赖
  • STM32单片机,UART的寄存器配置以及工作原理

    UART是重要的片上资源 主流单片机基本上都有该功能 通过UART可以扩展出很多的通信接口 如RS232 RS485 LIN 甚至WIFI 蓝牙模组等 可以说只要搞通讯就会涉及到UART 下面和大家分享STM32的UART配置 1 UART
  • CF1604C Di-visible Confusion

    CF传送门 早上起来看一下昨天的cf div2 后悔昨天没打了 本题是一道很水的思维题 题目的大意就是说 如果选择序列 a a a的第 i i i位 如果 a
  • C语言计算代码执行时间的办法

    在Linux下 sleep 单位为秒 usleep 里面的单位是微秒 在Windows系统中 sleep 单位为毫秒 有两个和计算执行时间相关的函数 在调试分析性能的时候 我们经常需要检查一段代码执行花了多少时间 下面的例子说明在C语言里面
  • OpenCV各个模块介绍

    对于初学opencv的我来说 最头疼和无法下手的就是 都有什么库 那些库都是干什么的 怎么用 我想很多人应该和我一样 我觉得最重要的就是需要先知道opencv有哪些库 都是干什么的 在我们安装opencv的地址下 可以看到opencv2中包
  • 使用rpm包搭建Glusterfs集群

    使用rpm搭建Glusterfs集群步骤 一 环境准备 1 准备搭建glusterfs所需的rpm包 centos release gluster6 1 0 1 el7 centos noarch rpm centos release st
  • mysql中空值和null值的区别及处理方法总结

    一直对空值和null值的概念理解不清晰 所以结合资料以及自己的理解对他们的区别和处理方式进行总结 首先就是在概念上的不同 1 空值不占空间 2 null值占空间 打个比喻就是空值表示一个杯子是真空状态 什么都没有 而null值是杯子中有空气
  • Java 8 中的抽象类和接口到底有啥区别?

    在我们面试时也会经常遇到面试官问抽象类和接口的区别是什么 大部人肯定会说 接口中的所有方法都是抽象的 抽象类中的方法除了抽象方法还可以写实现方法 如果你还这样回答那你就 OUT 啦 要跟上形式 这个问题我在面试一个 39 岁的程序员时 他居
  • Redis配置文件解读

    转载自 http www cnblogs com daizhj articles 1956681 html 对部分配置选项做了一些说明 把配置项目从上到下看了一遍 有了个大致的了解 暂时还用不到一些高级的配置选项 先放在这 用到的时候再回来
  • Teradata SQL 线性回归函数

    基于budget amounts排队得到前三个部门 显示部门号和预算 SELECT department number salary amount RANK salary amount AS Rank FROM dapartment QUA
  • Typescript(九)配置文件 tsconfig.json

    TypeScript 使用 tsconfig json 文件作为其配置文件 当一个目录中存在 tsconfig json 文件 则认为该目录为 TypeScript 项目的根目录 通常 tsconfig json 文件主要包含两部分内容 指
  • unity

    一 理解我们要做的事 原本图片放入文件夹后是Default 默认 模式 但是需要大量处理图片的时候 我们希望它拖进去就是sprite模式 我们想修改unity原本的功能 二 unity是允许我们去修改它本身的一些功能的 你可以定制属于你的u
  • JVM系列(十) 垃圾收集器之 Parallel Scavenge/Old

    上篇文章我们讲解了单线程垃圾收集器 Serial SerialOld 与之相对应的多线程垃圾收集器就是 Parallel Scavenge Old 本文我们讲解下多线程垃圾收集器 Parallel Scavenge Old 垃圾收集器 新生