GC 垃圾回收算法、垃圾回收器及 JVM 调优【JVM知识点-resu】

news2024/12/25 0:30:09

JVM知识点

  • 详情请见:垃圾回收算法、垃圾收集器
  • 详情请见:JVM调优

1 GC垃圾回收算法

众所周知,Java的内存管理是交由了JVM,那么程序时时刻刻都在产生新对象,为了避免内存溢出,此时必然会涉及到垃圾回收(Garbage Collect)。

前置:

  1. 如何确定一个对象是垃圾?
  • 引用计数法(循环引用问题)
  • 可达性分析【从GC Root对象开始向下寻找,看某个对象是否可达。】
    • GC Root:类加载器、Thread、虚拟机栈本地变量表、static成员、常量引用、本地方法栈
  1. 什么时候会回收垃圾?
  • Eden或S区不够用
  • 老年代区不够用
  • 方法区不够用
  • System.gc()

1.1 标记-清除(Mark-Sweep)

  1. 标记
    • 找出内存中需要回收的对象,并标记出来(扫描堆中所有对象,耗时)
  2. 清除
    • 清除被标记对象

1.2 标记- 复制 (Mark-Copying)

当其中一块内存使用完了,就将还存活的对象复制到另一块上面,然后把已经使用过的内存空间一次性清除掉。

缺点:利用率低。1/2空间被浪费。

1.3 标记-整理(Mark-Compact)

在标记-清除的基础上,多一了一个整理,腾出来连续的内存空间

1.4 总结

上面介绍了3种垃圾回收算法,那么在java的堆种到底使用哪一个呢?

  • Young区:复制算法(Young区对象生命周期短,复制效率高)
  • Old区:标记清除或标记整理(Old区对象存活时间长)

2 垃圾回收器

如果说垃圾回收算法是内存回收的方法论,那么垃圾收集器就是垃圾回收的具体实现。

在这里插入图片描述

2.1 Serial(Young、复制)

单线程,简单高效,垃圾收集的时候需要暂停其他线程,采用复制算法,新生代使用

单线程收集器,不仅仅意味着它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的
是其在垃圾收集的时候需要暂停其他线程。

-- 优点:简单高效,拥有很高的单线程收集效率
-- 缺点:收集过程需要暂停所有用户线程
-- 算法:复制算法
-- 适用范围:新生代
-- 应用:Client模式下的默认新生代收集器

在这里插入图片描述

2.2 Serial Old(Old区、标整)

单线程,需要暂停用户线程,Serial的老年代版,采用标记-整理算法,老年代使用
在这里插入图片描述

2.3 ParNew(Serial的多线程版本)

多线程,多CPU下效率更高,Serial的多线程版本,采用复制算法,新生代使用

优点:在多CPU时,比Serial效率高
缺点:收集过程暂停所有用户线程,单CPU时比Serial效率差
算法:复制算法
适用范围:新生代
应用:运行在Server模式下的虚拟机中首选的新生代收集器

在这里插入图片描述

2.4 Parallel Scavenge(Young区,多线程,吞吐量+)

多线程,更关注系统吞吐量(每秒处理请求数),采用复制算法,新生代使用

吞吐量:系统单位时间内所处理的信息量
吞吐量=运行用户代码的时间 /(运行用户代码的时间+垃圾收集的时间)
比如:虚拟机一共运行了100分钟,垃圾收集时间用了1分钟,吞吐量=(100-1)/100=99%

若吞吐量越大,意味着垃圾收集的时间越短,则用户代码可以充分利用CPU资源,尽快完成程序的运算任务。

-XX:MaxGCPauseMillis 控制最大的垃圾收集停顿时间
-XX:GCRatio		 直接设置吞吐量大小

2.5 Parallel Old(Old区、多线程、标整、吞吐量+)

多线程,Parallel Scavenge的老年代版本采用标记-整理算法,也是更加关注系统的吞吐量,老年代使用

2.6 CMS(Old区,垃圾、用户线程并发、标清)

某个阶段内存回收与用户线程一起并发执行,最短回收停顿时间为目标,采用标记-清除算法,用于Old区

(1)初始标记 initial mark 		 标记GC Roots直接关联对象,不同Tracing,速度很快
(2)并发标记 concurrent mark	 	 进行GC Roots Tracing
(3)重新标记 remark		 	     修改并发标记因用户程序变动的内容
(4)并发清除 concurrent sweep    清除不可达对象回收空间,同时有新垃圾产生,留着下次
 								 清理称为浮动垃圾

由于整个过程中,有并发标记和并发清除,收集器线程可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行。

在这里插入图片描述

优点:并发收集、低停顿
缺点:产生大量空间碎片、并发阶段会降低吞吐量

2.7 G1(Young、Old;Region,标整,用户期望回收time)

保留分代概念,采用标记-整理算法,让用户设置停顿时间

将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留着新生代与老年代的概念,但是新生代和老年代不再是物理隔离的,它们都是一部分Region(不需要连续)的集合。

在这里插入图片描述

在这里插入图片描述

2.8 ZGC(Page、10ms以内)

号称零停顿,没有新老年代概念,将堆划分为一个个Page
特点:

  1. 可以达到10ms以内的停顿时间要求
  2. 支持TB级别的内存
  3. 堆内存变大后停顿时间还是在10ms以内

在这里插入图片描述

3 JVM调优

3.1 常见参数

①标准参数

-version
-help
-server
-cp

②-X参数(非标准)

非标准参数,在JDK各个版本中可能会变动

-Xint    	解释执行
-Xcomp		编译执行(第一次使用就编程本地代码)
-Xmixed		混合模式,由JVM自己决定

在这里插入图片描述

使用时需要加上-version,之前说过java是编译+解释执行的语言,此处可以调整

③-XX参数(非标准,重要)

使用的最多的参数

  • 非标准化参数,相对不稳定,主要用于JVM调优合Debug
a.Boolean类型
格式: -XX:[+-]<name>	+或-表示启动或禁用name属性
比如: -XX:+UseConcMarkSweepGC 表示启用CMS垃圾收集器
	  -XX:+UseG1GC			  表示启用G1类型得垃圾收集器
b.非Boolean类型"直接设数值"
格式:-XX<name>=<value>	表示name属性得值是value
比如:-XX:MaxGCPauseMillis=500

④其他参数(简写)

-Xms1000M等价于-XX:InitialHeapSize=1000M
-Xms1000M等价于-XX:MaxHeapSize=1000M
-Xss100等价于-XX:ThreadStackSize=100

所以这块也相当于-XX类型的参数

⑤查看参数

java -XX:+PrintFlagsFinal -version
java -XX:+PrintFlagsFinal -version > flags.txt --导出到flags文件(linux环境下)

在这里插入图片描述

需要注意的是"=“表示默认值,”:="表示被用户或JVM修改后得值
如果我们想要查看某个进程具体参数得值,可以使用jinfo命令
一般来说,我们设置参数之前,可以先查看一下当前参数是什么,然后进行修改

⑥设置参数的常见方式

  • 开发工具中设置,如IDEA、Eclipse
  • 运行jar包的时候:java -XX:+UseG1GC xxx.jar
  • web容器比如tomcat,可以在脚本中进行设置
  • 通过jinfo实时调整某个进程的参数(参数只有被标记为manageable的flags才可以被实时修改)

⑦常用参数汇总

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 常见命令

①jps(查看java进程)

在这里插入图片描述

②jinfo(查看、修改属性值)

(1)实时查看和调整JVM配置参数
(2)查看用法
jinfo -flag name PID	查看进程号为PID的某个java进程name属性的值

例:
jinfo -flag MaxHeapSize PID
jinfo -flag UseG1GC PID

在这里插入图片描述

(3)修改
参数只有被标记为manageable的flags才可以被实时修改
jinfo -flag [+|-] PID
jinfo -flag <name>=<value> PID
(4)查看曾经赋值过的一些参数
jinfo -flags PID

在这里插入图片描述

③jstat(查看垃圾收集信息、类装载信息)

  1. 查看虚拟机性能统计信息
  2. 查看类装载信息

jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,一共输出10次

在这里插入图片描述
3. 查看垃圾收集信息

jstat -gc PID 1000 10

在这里插入图片描述

④jstack(查看堆栈信息、排查死锁)

查看线程堆栈信息

jstack PID

在这里插入图片描述

  1. 写一个死锁Demo
  • 排查死锁(DeadLockDemo)
public class DeadLockDemo {
    public static void main(String[] args) {
        DeadLock d1 = new DeadLock(true);
        DeadLock d2 = new DeadLock(false);
        Thread t1 = new Thread(d1);
        Thread t2 = new Thread(d2);
        t1.start();
        t2.start();
    }
}

//定义锁对象
class MyLock{
    public static Object obj1 = new Object();
    public static Object obj2 = new Object();
}

//死锁代码
class DeadLock implements Runnable{
    private boolean flag;
    DeadLock(boolean flag){
        this.flag = flag;
    }
    public void run(){
        if(flag){
            while(true){
                synchronized (MyLock.obj1){
                    System.out.println(Thread.currentThread().getName() + "----if获得obj1锁");
                    synchronized (MyLock.obj2){
                        System.out.println(Thread.currentThread().getName() + "----if获得obj2锁");
                    }
                }
            }
        } else {
            while (true){
                synchronized (MyLock.obj2){
                    System.out.println(Thread.currentThread().getName() + "----否则获得obj2锁");

                    synchronized (MyLock.obj1){
                        System.out.println(Thread.currentThread().getName() + "----否则获得obj1锁");
                    }
                }
            }
        }
    }
}
jps -l # 查看java进程信息
jstack 5140 查看堆栈信息

在这里插入图片描述

将打印信息拉到最后

在这里插入图片描述

⑤jmap(查看堆内存信息)

  1. 生成堆转储快照
  2. 打印出堆内存相关信息

jmap -heap PID

在这里插入图片描述
3. dump出堆内存相关信息

jmap -dump:format=b,file=heap.hprof PID

在这里插入图片描述
这个时候我们会想,要是在发生堆内存溢出得时候,能够自动dump出该文件就好了

  • 一般我们在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件
  • -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof

3.3 调优实战

在这里插入图片描述

①前置

  • JVM调优不是常规手段,性能问题一般第一选择是优化程序,最后的选择才是进行JVM调优。
  • JVM的自动内存管理本来就是为了将开发人员从内存管理的泥潭里拉出来。即使不得不进行JVM调优,也绝对不能拍脑门就去调整参数,一定要全面监控,详细分析性能数据。

②调优时机

  1. Heap(老年代)内存持续上涨到设置的最大值
  2. Full GC次数频繁
  3. GC停顿时间过长(超过1秒)
  4. 应用出现OOM等内存异常
  5. 应用中有使用本地缓存且占用大量内存空间
  6. 系统吞吐量与响应性能那个不高,甚至出现下降

③调优目标

吞吐量、延迟、内存占用三者类似CAP,构成了一个不可能三角,只能选择其中两个进行调优,不可三者兼得。

  • 延迟:GC低停顿和GC低频率
  • 低内存占用
  • 高吞吐量

选了其中两个必然会以牺牲另外一个为代价。

JVM调优的量化目标参考实例:

  • Heap内存使用率 <= 70%
  • Old generation内存使用率 <= 70%
  • avg pause <= 1s
  • Full GC次数为0或avg pause interval >= 24h

注意:不同的JVM调优量化目标是不同的

④调优步骤

  1. 分析系统运行情况,如GC日志、dump文件,判断是否需要调优
  2. 确定JVM调优量化目标
  3. 确定JVM调优参数(根据历史JVM参数来调整)
  4. 一次确定调优内存、延迟、吞吐量等指标
  5. 对比观察调优前后的差异
  6. 不断分析和调整,直到找到合适的JVM参数配置
  7. 找到最合适的参数后,将这些参数应用到所有服务器,并进行后续的跟踪

在这里插入图片描述

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

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

相关文章

【MySQL数据库原理】Python3.7 中连接 MySQL 数据库

目录 1、安装mysql-connector-python2、连接 MySQL 数据库3、修改数据库1、安装mysql-connector-python 要在 Python 中连接 MySQL 数据库 “test”,可以使用 “mysql-connector-python” 包。首先,确保已经安装了该包。可以使用 pip 命令进行安装: pip install mysql-con…

[abc复盘] abc297 20230409

[atc复盘] abc297 20230409 一、本周周赛总结A - Double Click1. 题目描述2. 思路分析3. 代码实现B - chess9601. 题目描述2. 思路分析3. 代码实现C - PC on the Table1. 题目描述2. 思路分析3. 代码实现D - Count Subtractions1. 题目描述2. 思路分析3. 代码实现E - Kth Takoy…

Spring 04 -SpringAOP开发

SpringAOP开发SpringAOP1 原理2 动态代理2.1 JDK动态代理2.2.2 Cglib动态代理2.2.3 **JDK动态代理和Cglib动态代理**3 SpringAOP3.1 AOP专业术语3.2 环境搭建3.3 基于XML配置3.4 基于注解配置2.5 通知类型面向切面编程&#xff0c;在不修改源代码的情况加&#xff0c;对类功能实…

人工智能中的顶级会议

当搭建好了AI领域的知识架构&#xff0c;即具备了较好的数学、编程及专业领域知识后&#xff0c;如果想在AI领域追踪前沿研究&#xff0c;就不能再只看教材了。毕竟AI领域的发展一日千里&#xff0c;教材上的知识肯定不是最新的。此时&#xff0c;应该将关注的重点转向AI领域的…

JavaWeb - Web网站的组成,工作流程以及开发模式

一. Web Web&#xff1a;全球广域网&#xff0c;也称玩万维网(www Wrold Wide Web)&#xff0c;就是能够通过浏览器访问的网站学习Web开发&#xff0c;其实就是要使用Java这门语言来开发这样的Web网站&#xff0c;这也是现在Java语言最主流的企业级应用方式。使用Java语言开发…

Nginx基本配置 Nginx服务基础Nginx访问控制Nginx虚拟主机

本章结构 Nginx服务基础 Nginx访问控制 Nginx虚拟主机 原理&#xff1a; 关于Nginx 一款高性能、轻量级Web服务软件 稳定性高 系统资源消耗低 apache多线程或多进程实现连接&#xff08;多线程比多线程稍微好些&#xff0c;切换资源浪费少&#xff09; Nginx单线程 对HTTP并发…

自己动手写CPU——第二篇

1 ori指令说明 ori是进行逻辑 或 运算的指令&#xff0c;其指令格式如下所示 从以上的指令格式&#xff0c;我们可以直到&#xff0c;这是一个I类型指令&#xff0c;ori指令的指令码是 6‘b001101&#xff0c;所以当处理器发现正在处理的指令的高6bit 是 001101 的时候&#x…

vue3 css相关知识与动态style

scoped 当 <style> 标签带有 scoped attribute 的时候&#xff0c;它的 CSS 只会影响当前组件的元素&#xff0c;和 Shadow DOM 中的样式封装类似。 <style scoped lang"scss"> </style> 注意 &#xff1a; 作用域样式并没有消除对 class 的需求…

DN-DETR源码学习记录

DN-DETR是在DAB-DETR的基础上完成的&#xff0c;DN-DETR的作者认为导致DETR类模型收敛慢的原因在于匈牙利匹配所导致的二义性&#xff0c;即匈牙利算法匹配的离散性和模型训练的随机性&#xff0c;导致ground-truth的匹配变成了一个动态的、不稳定的过程。举个例子&#xff0c;…

字节青训营(前端)打卡day01_计网

计算机网络概论 1.前沿和课程介绍 自顶向下、自底向上 网络分层、网络协议、网络应用、HTTP123、CDN GPT. 计算机网络的发展历程可以分为四个阶段&#xff1a;单机、局域网、广域网、互联网 2.蟹堡王帝国 顾客&#xff1a;客户端 分店&#xff1a;服务端 小区转发点&…

【FFmpeg】编码器流程分析

目录1 编译2 调用关系2.1 第一帧没有获取到码流&#xff0c;第二帧获取到一帧码流2.2 送帧为NULL&#xff0c;刷新编码器获取剩余的全部码流3 总结4 感受1 编译 参考文件doc/examples/encode_video.c&#xff0c;使用x264作为编码器&#xff0c;需要先安装x264&#xff0c;编译…

如何用ChatGPT写毕业论文?

老早之前就听说有同学用ChatGPT写论文了 但是一直不觉得人工智能够真的替代人类 正好最近毕业论文开始降重了&#xff0c;超高的重复率愁得我快睡不着了 刷微博突然看到这个有关ChatGPT的问题。 出于好奇的我决定先来试试这个ChatGPT到底能不能帮我解决降重问题哈哈哈 点击…

shell脚本基础之处理脚本输入

处理输入命令行参数读取参数读取脚本名测试参数特殊参数变量参数统计获取所有参数移动变量处理选项查找选项处理简单选项分离选项和参数处理带值的选项getopt 命令命令格式在脚本中使用getoptgetopts命令脚本选项标准化获取用户的输入基本的读取超时隐藏式读取文件中读取在此之…

Linux命令·ifconfig

许多windows非常熟悉ipconfig命令行工具&#xff0c;它被用来获取网络接口配置信息并对此进行修改。Linux系统拥有一个类似的工具&#xff0c;也就是ifconfig(interfaces config)。通常需要以root身份登录或使用sudo以便在Linux机器上使用ifconfig工具。依赖于ifconfig命令中使…

OpenFeign#1 - FeignClient 是如何注册的?

文章目录EnableFeignClientsFeignClientsRegistrarregisterDefaultConfigurationregisterFeignClientsFeignClientFeignClientFactoryBeanFeignContextfeign(FeignContext)EnableFeignClients 该注解会导致 FeignClientsRegistrar 的注入. Retention(RetentionPolicy.RUNTIME…

Redis AOF

一、Redis AOF 1.简介 目前&#xff0c;redis的持久化主要应用AOF(Append Only File)和RDB两大机制。AOF以日志的形式来记录每个写操作(增量保存),将redis执行过的所有写指令全部记录下来(读操作不记录)。只许追加文件&#xff0c;但不可以改写文件。redis启动之初会读取该文…

自动化测试学习(七)-正则表达式,你真的会用吗?

目录 一、正则表达式在python中如何使用 二、用正则表达式匹配更多模式 三、常用字符分类的缩写代码 总结 所谓正则表达式&#xff08;regex&#xff09;&#xff0c;就是一种模式匹配&#xff0c;学会用正则匹配&#xff0c;就可以达到事半功倍的效果。 一、正则表达式在…

工程管理系统软件 自主研发,工程行业适用

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

在 Web3 里如何寻找靠谱的创新路径——Solv V3 阶段性复盘(上)

作者&#xff1a;Solv 核心团队Solv V3 是 3 月 21 日发布的&#xff0c;到这周一整整三个星期。三周时间产生的实际交易额超过 6,000 万美元&#xff0c;预计在本月内能够破亿。而且从我们手上的 pipeline 来看&#xff0c;这个增长的势头还将持续下去。在几个月内&#xff0c…

「Long HK, Long Crypto」主题酒会在香港圆满举行!Web3er齐聚一堂共叙行业发展

「2023 香港 Web3 嘉年华」是香港有史以来规模最大的加密货币活动之一&#xff0c;邀请了300多位行业领袖、区块链项目创始人、投资人、监管机构代表、专家学者&#xff0c;为每一位参与者带来前沿的 Web3 技术&#xff0c;共同探讨 Web3 未来发展的关键问题。 Web3相关的各大…