JVM Optimization Learning(六)

目录

一、JVM Optimization

1、Shenandoah

Shenandoah的使用方法

2、ZGC

ZGC的版本更迭

ZGC的使用方法

ZGC的参数设置

3、JMH测试GC性能


一、JVM Optimization

1、Shenandoah

        Shenandoah是由Red Hat开发的一款低延迟的垃圾收集器,Shenandoah并发执行大部分GC工作,包括并发的整理,堆大小对STW的时间基本没有影响

Shenandoah的使用方法

1、下载:Shenandoah只包含在OpenJDK中,默认不包含在内,需要单独构建,可以直接下载构建好的。

Shenandoah下载地址

下载选择方式如下: 

1、{aarch64,arm32-hflt,mipsel,mips64el,ppc64le,s390x,x86_32,x86_64}:架构,linux中使用arch命令选择对应的架构。

[root@localhost ~]# arch
x86_64

2、{server,zero}:虚拟机类型,选择server,包含所有GC功能

3、{release,fastdebug,Slowdebug,optimization}:不同的优化级别,选择release,性能最高。

4、{gcc*glibc*,msvc*}:编译期版本,选择较高的版本性能好一些,如果兼容性有问题,(无法启动)选择较低的版本。--glibc版本选择

[root@localhost ~]# ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
[root@localhost ~]#

centos版本低。重新安装ubuntu操作系统22.4.3版本

root@admin:~# ldd --version
ldd (Ubuntu GLIBC 2.35-0ubuntu3.5) 2.35
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
root@admin:~#

我这里选择的版本:openjdk-jdk-shenandoah-linux-x86_64-server-release-gcc10-glibc2.31.tar.xz

root@admin:/usr/java# java -version
openjdk version "22-testing" 2024-03-19
OpenJDK Runtime Environment (build 22-testing-builds.shipilev.net-openjdk-jdk-shenandoah-b171-20231209)
OpenJDK 64-Bit Server VM (build 22-testing-builds.shipilev.net-openjdk-jdk-shenandoah-b171-20231209, mixed mode, sharing)

2、配置。将OpenJDK配置到环境变量中,使用java -version进行测试。打印出如下内容代表成功。

3、添加参数,运行Java程序

-XX:+UseShenandoahGC 开启Shenandoah GC

-Xlog:gc 打印GC日志

2、ZGC

ZGC文章

The Z Garbage Collector (ZGC) is a scalable low latency garbage collector. ZGC performs 
all expensive work concurrently, without stopping the execution of application threads 
for more than a millisecond. It is suitable for applications which require low latency.
Pause times are independent of the heap size that is being used. ZGC works well with 
heap sizes from a few hundred megabytes to 16TB. ZGC was initially introduced as an experimental feature in JDK 11, and was declared 
Production Ready in JDK 15. In JDK 21 was reimplemented to support generations.Z垃圾收集器(ZGC)是一种可扩展的低延迟垃圾收集器。ZGC执行所有昂贵的工作都是并发的,而不会停止
应用程序线程的执行持续超过一毫秒。它适用于需要低延迟的应用程序。暂停时间与正在使用的堆大小无关。
ZGC与堆大小从几百兆字节到16TB。
ZGC最初是作为JDK 11中的一个实验特性引入的,并声明JDK 15中的生产就绪。JDK中重新实现了21,以支持几代人。

        ZGC(Z Garbage Collector)是一款基于Region内存布局的,暂时不设分代的,使用了读屏障、颜色指针等技术来实现可并发的,采用标记-整理算法的,以低延迟为首要目标的一款垃圾收集器。

        ZGC是一种可扩展的低延迟垃圾回收器。ZGC在垃圾回收过程中,STW的时间不会超过一毫秒,适合需要低延迟的应用。支持几百兆到16TB的堆大小,堆大小对STW的时间基本没有影响。

        ZGC降低了停顿时间,能降低接口的最大耗时,提升用户体验。但是吞吐量不佳,所以如果Java服务比较关注QPS(每秒的查询次数),那么G1是比较不错的选择。

内存布局

        跟G1类似,ZGC的堆内存也是基于Region来分布。不同的是,ZGC的Region支持动态地创建和销毁,并且Region的大小不是固定的,包括三种类型的Region:

Smail Region:2MB,主要用于放置小于256KB的小对象。

Medium Region:32MB,主要用于放置大于等于256KB小于4MB的对象。

Large Region:N * 2MB,这个类型的Region是可以动态变化的,不过必须是2MB的整数倍,最小支持4MB,每个Large Region只放置一个大对象,并且是不会被重分配的。

颜色指针

颜色指针,如下图所示,是ZGC的核心设计之一。以前的垃圾回收器的GC信息都保存在对象头中,而ZGC的GC信息保存在指针中。

每个对象有一个64位指针,这64位被分为:

        18位:预留给以后使用。

        1位:Finalizable标识。

        1位:Remapped标识,是否进入了重分配集(即被移动过)。

        1位:Marked1标识,简称M1。

        1位:Marked0标识,和上面的Marked1都是用于辅助GC。简称M0。

        42位:对象的地址(所以它可以支持2^42=4T内存)。

垃圾收集过程

大概分为4个阶段:并发标记,并发预备重分配,并发重分配,并发重映射。

        并发标记(Concurrent Mark):与G1一样,并发标记是遍历对象,做可达性分析的阶段。前后也要经过类似G1的初始标记、最终标记的短暂停顿。与G1不同的是,ZGC的标记是在指针上而不是在对象上进行的,标记阶段会更新颜色指针的M0/M1标志位。

        并发预备重分配(Concurrent Prepare for Relocate):这个阶段根据特定的查询条件统计出本次收集过程要清理哪些Region,将这些Region组成重分配集(Relocate Set)。重分配集与G1收集器的回收集(Collection Set)还是有区别的,ZGC划分Region的目的并非为了像G1那样做收益优先的增量回收。相反,ZGC每次回收都会扫描所有的Region。

        并发重分配(Concurrent Relocate):该阶段是ZGC执行过程中的核心阶段,这个过程要把重分配集中的存活对象复制到新的Region上,并为重分配集中的每个Region维护一个转发表(Forward Table),记录从旧对象到新对象的转向关系。得益于颜色指针的支持,ZGC收集器能仅从引用上就明确得知一个对象是否处于重分配分配集之中,如果用户线程此时并发访问了位于重分配集中的对象,这次访问将被读屏障所截获,然后立即根据Region上的转发表记录将访问转发到新复制的对象上,并同时修正更新该引用的值,使其直接指向新对象,ZGC的这种行为称作指针的“自愈”能力。

        并发重映射(Concurrent Remap):该阶段所做的主要是修正整个堆中指向重分配集中旧对象的所有引用。但是ZGC的并发重映射并不是必须要“迫切”去完成的任务。因为即使是旧引用,它也是可以自愈的,最多只是第一次使用时多一次转发和修正操作。因此,ZGC很巧妙的将并发重映射阶段要做的工作,合并到了下一次GC中的并发标记阶段里去完成,反正它们都是要遍历对象,这样就节省了一次遍历的开销。一旦所有的指针被修正之后,原来记录新旧关系的转发表就可以释放掉了。

ZGC的版本更迭

        2018年JDK11,实验版本。2019年JDK12-13,并行类的卸载AArch64架构支持。

        2020年JDK14-15,windows & MacOS支持第一个正式版本。

        2021年JDK16-17,亚毫秒级最大暂停时间并行线程数的自动计算。

        2023年JDK21,支持分代年龄。

ZGC的使用方法

        OracleJDK和OpenJDK中都支持ZGC,阿里的DragonWell龙井JDK也支持ZGC但属于其自行对OpenJDK11的ZGC进行优化的版本。

        建议使用JDK17之后的版本,延迟较低同时无需手动配置并行线程数

分代ZGC添加参数启用:-XX:+UseZGC -XX:+ZGenerational

非分代ZGC通过命令行选项启用:-XX:+UseZGC

ZGC的参数设置

需要设置的参数:

-Xmx值最大堆内存大小

        这是ZGC最重要的一个参数,必须设置。ZGC在运行过程中会使用一部分内存来处理垃圾回收,所以尽量保证堆中有足够的空间。设置多少值取决于对象分配的速度,根据测试情况来决定。

可以设置的参数

-XX:SoftMaxHeapSize=值

        ZGC会尽量保持堆内存小于该值,这样在内存靠近这个值时会尽早地进行垃圾回收,但是依然有可能会超过该值。例如:-Xmx5g -XX:SoftMaxHeapSize=4g 这个参数设置,ZGC会尽量保证堆内存大小4GB,最多不会超过5GB。

3、JMH测试GC性能

pom

<properties><java.version>21</java.version>
</properties><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.37</version>
</dependency>
<dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.37</version>
</dependency>

测试代码:

package com.lwz;import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;//执行5轮预热,每次持续2秒
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
//输出毫秒单位
@OutputTimeUnit(TimeUnit.MILLISECONDS)
//统计方法执行的平均时间
@BenchmarkMode(Mode.AverageTime)
//java -jar xxx.jar -rf json
@State(Scope.Benchmark)
public class JavaGc {//每次测试对象大小4KB和4M@Param({"4", "4096"})int perSize;private void test(Blackhole blackhole) {//每次循环创建堆内存60%对象 JMX获取到Java运行中的实时数据MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();//获取到剩余的堆内存大小long heapSize = (long) ((heapMemoryUsage.getMax() - heapMemoryUsage.getUsed()) * 0.6);//计算循环的次数long size = heapSize / (1024L * perSize);for (int i = 0; i < 4; i++) {List<byte[]> list = new ArrayList<>((int) size);for (int j = 0; j < size; j++) {list.add(new byte[1024 * perSize]);}blackhole.consume(list);}}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseSerialGC"})public void serialGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseParallelGC"})public void parallelGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g"})public void g1(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseShenandoahGC"})public void shenandoahGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseZGC"})public void zGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseZGC","-XX:+ZGenerational"})public void zGcGenerational(Blackhole blackhole){test(blackhole);}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(JavaGc.class.getSimpleName()).forks(1).build();new Runner(opt).run();}
}

JVM Optimization Learning(五)

再小的努力,乘以365都很明显!
一个程序员最重要的能力是:写出高质量的代码!!
有道无术,术尚可求也,有术无道,止于术。
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/211899.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器人纯阻抗控制接触刚性环境(阻尼影响因素)

问题描述 在机器人学中&#xff0c;阻抗控制是一种常用的控制策略&#xff0c;用于管理机器人在与环境交互时的运动和力。阻抗控制背后的关键概念是将环境视为导纳&#xff0c;而将机器人视为阻抗。 纯阻抗控制接触刚性环境时&#xff0c;机器人的行为方式主要受其阻抗参数的…

【开源】基于Vue和SpringBoot的车险自助理赔系统

项目编号&#xff1a; S 018 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S018&#xff0c;文末获取源码。} 项目编号&#xff1a;S018&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车…

Maven基础

目录 Maven坐标 坐标简介 主要组成 Maven依赖管理 配置依赖 依赖简介 配置依赖 依赖传递 依赖传递简介 排除依赖 依赖范围 生命周期 生命周期简介 执行指定生命周期 Maven坐标 坐标简介 Maven中的坐标是资源的唯一标识&#xff0c;通过该坐标可以唯一定位资…

Python开发运维:Python调用K8S API实现资源管理

目录 一、实验 1.Python操作K8S API获取资源 2.Python操作K8S API创建deployment资源 3.Python操作K8S API删除k8s资源 4.Python操作K8S API修改k8s资源 5.Python操作K8S API查看k8s资源 二、问题 1.Windows11安装kubernetes报错 2.Python通过调用哪些方法实现Pod和De…

在SpringData JPA 中实现对持久层的操作

1.导入依赖 hibernate 这个依赖自带实现JPA接口 <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><depen…

CrystalDiskInfo中文版(硬盘检测工具) v9.1.1.0 绿色汉化版-供大家学习研究参考

更新内容 重新支持三星SATA SSD寿命报告 增加对ZHITAI SC001的支持 新增SK hynix Gold S31支持 增加了KLEVV NEO N610的支持。 改进的Micron/Crucial SATA SSD支持 已更改 卸载程序将显示一个确认对话框&#xff0c;用于删除设置。 强大功能 1.拥有多国语言&#xff0c;…

045:Vue读取本地上传JSON文件,导出JSON文件方法

第045个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

jquery手写广告轮播图,无限循环功能

说明 在很多情况下&#xff0c;我们都需要开发广告轮播图&#xff0c;当我们进行页面的功能开发时&#xff0c;采用轮播图来实现也行&#xff0c;但是很多情况下&#xff0c;我们只需要简单的控制轮播循环轮播展示即可&#xff0c;所以用jq开开发广告轮播波&#xff0c;自定义…

Idea 插件开发: Swing Designer设计器创建的组件全部为空问题记录

问题现象 通过Swing 设计器创建的对象, Swing组件全部是空的, 导致ToolWindowFactory工厂的实现类调用时候出现了空指针异常 如下方式创建的 问题分析 问题出现时候, 同时给我生成了一个createUIComponents的私有方法, 由于个人当时理解有误, 把他当成了初始化方法, 在里面…

Oracle高可用一家老小全在这里

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

用Java实现一对一聊天

目录 服务端 客户端 服务端 package 一对一用户; import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; imp…

SpringBoot中MyBatis-Flex的集成和使用

一、MyBatis-Flex 是什么​ MyBatis-Flex是一个基于MyBatis的数据访问框架&#xff0c;专门为Flex应用程序而设计的。它提供了一种灵活而高效的方式来处理Flex应用程序中的数据访问&#xff0c;可以轻松地连接到各种数据源&#xff0c;并提供了一些方便的工具和功能&#xff0c…

delphi android打开外部文件,报错android.os.FileUriExposedException解决方法

Android 7.0强制启用了被称作 StrictMode的策略&#xff0c;带来的影响就是你的App对外无法暴露file://类型的URI了。 如果你使用Intent携带这样的URI去打开外部App(比如&#xff1a;打开系统相机拍照)&#xff0c;那么会抛出FileUriExposedException异常。 Delphi 为Android…

windows系统安装RocketMQ_dashboard

1.下载源码 按照官网说明下载源码 官网 官网文档 2.源码安装 2.1.① 编译rocketmq-dashboard 注释掉报错的maven插件frontend-maven-plugin、maven-antrun-plugin mvn clean package -Dmaven.test.skiptrue2.2.② 运行rocketmq-dashboard java -jar target/rocketmq-…

tamcat乱码

学习springmvc时tamcat乱码 ①、启动时tomcat控制台乱码 解决方法是&#xff1a;1、先把idea设置里的默认字节码改成utf-8 ​ 2、把idea显示编码改成utf-8&#xff0c;在末尾加上&#xff08; -Dfile.encodingUTF-8&#xff09; ​ 3、最后重启idea 加上这个 -Dfile.encodingU…

【软考中级——软件设计师】备战经验 笔记总结分享

考试成绩 我第一次备考是在2022 然后那时候取消了这次是第二次 靠前我一个月复习的看了以前的笔记 然后刷了七八道历年题目学习资料推荐 &#xff1a;zst——2021 b站链接自荐一下我的笔记 &#xff1a; 软考笔记专栏 视频确实很长 &#xff0c; 我的建议就是先看笔记 然后不会…

1-2、Java环境搭建

语雀原文链接 文章目录 1、JDK安装2、Hello World2-1、Hello World示例2-2、类名和文件名2-3、注释2-4、javadoc 3、环境变量3-1、Path作用3-2、classpath3-3、JAVA_HOME 4、Java组成5、跨平台原理5-1、Java跨平台原理5-2、C语言的跨平台原理 1、JDK安装 下载地址&#xff1a…

打造Github首页的动态飞线效果

一、导语 Github首页的地球动态飞线&#xff0c;大家都比较熟悉吧 二、分析 由大量随机的3点构造出贝塞尔曲线&#xff0c;然后开始从起点到终点的飞行后&#xff0c;然后再从起点到终点的消失&#xff0c;就此完成整个过程 三、基础代码 createCurve(startPoint, endPoint…

unity 2d 入门 飞翔小鸟 死亡闪烁特效(十三)

一、c#脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Bling : MonoBehaviour {public Texture img;public float speed;public static bool changeWhite false;private float alpha0f;// Start is called before the fi…

芯片量产导入知识

什么是芯片量产 从芯片功能设计到生产制造、测试等环节&#xff0c;每一个环节都至关重要。 对于保障大规模发货后芯片指标表现的一致性&#xff0c;以及产品应用生命周期内的稳定性和可靠性&#xff0c;需要考虑多种因素。以下是一些相关的观点&#xff1a; 可量产性设计&am…