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 的相关文章

  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • 两个有序数组合并成一个有序数组——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 垃圾收集器 新生