JAVA开发(JAVA垃圾回收的几种常见算法)
JAVA GC 是JAVA虚拟机中的一个系统或者说是一个服务,专门是用于内存回收,交还给虚拟机的功能。
JAVA语言相对其他语言除了跨平台性,还有一个最重要的功能是JAVA语言封装了对内存的自动回收。俗称垃圾回收器。所以有时候我们不得不承认,我们写的每一行JAVA代码都是垃圾!
那么JAVA虚拟机中,对应内存的回收常见的有哪些的呢。 我知道的有:
标记清除法、标记整理算法、复制清除、分代收集;其中最常用的是分代收集。
标记清除法:
示意图:

初始状态是一块空白未被使用的内存。java语言类中声明的对象运行,在堆中使用内存块。红的和绿的部分。
过了一段时间,垃圾回收器工作,检测哪些对象在使用,哪些对象不使用了进行标记。绿色部分为存活对象,红色部分为被标记。
然后将红色可回收的对象,清除释放内存。
优点:效率很高,快速。
缺点:使内存碎片化,不方便分配大内存。
标记整理算法:
示意图:

标记整理法比标记法多做一步工作,就是标记清除后,对碎片进行整理,移动。空出更大的内存块。
优点:尽可能空闲出较大块的内存块。
缺点:垃圾回收器比较忙碌。在移动内存对象过程中,消耗性能和效率。
复制清除:
示意图:

复制清除法可用内存一分为二,每次只用一块,当这一块内存不够用时,便触发 GC,将当前存活对象复制(Copy)到另一块上,以此往复 Java 对象的存活时间极短。
Java 对象高达 98% 是朝生夕死的,这也意味着每次 GC 可以回收大部分的内存,需要复制的数据量也很小,这样它的执行效率就会很高。
优点:效率高
缺点:只能使用50%的内存。
分代收集法:
示意图:

分代收集法:
根据对象一般都是先在 Eden区创建
当Eden区满,触发 Young GC,此时将 Eden中还存活的对象复制到 S0中,并清空 Eden区后继续为新的对象分配内存
当Eden区再次满后,触发又一次的 Young GC,此时会将 Eden和S0中存活的对象复制到 S1中,然后清空Eden和S0后继续为新的对象分配内存
每经过一次 Young GC,存活下来的对象都会将自己存活次数加1,当达到一定次数后,会随着一次 Young GC 晋升到 Old区
Old区也会在合适的时机进行自己的 GC。
新生代(Young generation)
绝大多数新创建的对象都会被分配到这里,这个区域触发的垃圾回收称之为:Minor GC 。
空间结构:
默认情况下,新生代(Young generation)、老年代(Old generation)所占空间比例为 1 : 2 。
它被分成三个空间:
· 1个伊甸园空间(Eden)
· 2个幸存者空间(Fron Survivor、To Survivor)
默认情况下,新生代空间的分配:Eden : Fron : To = 8 : 1 : 1
为什么要这样的布局?是因为新生代里的对象绝大多数是朝生夕死的,非常适合使用标记-复制算法,后面的回收算法章节会详细说。
新生代GC收集的执行顺序如下:
1、绝大多数新创建的对象会存放在伊甸园空间(Eden)。
2、在伊甸园空间执行第 1 次GC(Minor GC)之后,存活的对象被移动到其中一个幸存者空间(Survivor)。
3、此后每次 Minor GC,都会将 Eden 和 使用中的Survivor 区域中存活的对象,一次性复制到另一块空闲中的Survivor区,然后直接清理 Eden 和 使用过的那块Survivor 空间。
4、从以上空间分配我们知道,Survivor区内存占比很小,当空闲中的Survivor空间不够存放活下来的对象时,这些对象会通过分配担保机制直接进入老年代。
5、在以上步骤中重复N次(N = MaxTenuringThreshold(年龄阀值设定,默认15))依然存活的对象,就会被移动到老年代。
从上面的步骤可以发现,两个幸存者空间,必须有一个是保持空的。
我们需要重点记住的是,新创建的对象,是保存在伊甸园空间的(Eden)。那些经历多次GC依然存活的对象会经由幸存者空间(Survivor)转存到老年代空间(Old generation)。
也有例外出现,对于一些大的对象(指需要占用大量连续内存空间的对象)则直接进入到老年代。
Java提供了 -XX:PretenureSizeThreshold 来指定对象大于这个值,直接分配到老年代。
老年代(Old generation)
对象在新生代周期中存活了下来的,会被拷贝到这里。通常情况下这个区域分配的空间要比新生代多。正是由于对象经历的GC次数越多越难回收,加上相对大的空间,发生在老年代的GC次数要比新生代少得多。这个区域触发的垃圾回收称之为:Major GC 或者 Full GC
老年代空间的构成其实很简单,它不像新生代空间那样划分为几个区域,它只有一个区域,里面存储的对象并不像新生代空间里绝大部分都是朝闻道,夕死矣。这里的对象几乎都是从Survivor 空间中熬过来的,它们绝不会轻易狗带。因此,Major GC 或 Full GC 发生的次数不会有 Minor GC 那么频繁。
2、老年代使用的是标记-整理算法,清理完成内存后,还得把存活的对象重新排序整理成连续的空间,成本更高。
优点:低频率触发GC,更好的触发内存回收。
下面才是重点:知道了原理那怎么使用或者制定使用GC。java虚拟机中有很多种GC,我们可以通过配置指定,语法:
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:UseParallelGC -XX:ParallelGCThreans = 20
-Xmx3800m:最大堆大小
-Xms3800m:初始堆大小,此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2g: 设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,
不能无限生成,经验值在3000~5000左右。
-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即该配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。
-XX:ParallelGCThreans = 20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值的配置最好与处理器数目相等。
--------------------------------------------------------------------------------------------------------------------------
常见配置汇总
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n:设置持久代大小
堆设置
收集器设置
垃圾回收统计信息
并行收集器设置
并发收集器设置
调优总结
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
-XX:MaxHeapFreeRatio=30
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时
间。最优化的方案,一般需要参考以下数据获得:减少年轻代和年老代花费的时间,一般会提高应用的效率
吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
并发垃圾收集信息
持久代并发收集次数
传统GC信息
花在年轻代和年老代回收上的时间比例
响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
年轻代大小选择
年老代大小选择
较小堆引起的碎片问题
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
-XX:MaxHeapFreeRatio=30
相关文章:
JAVA开发(JAVA垃圾回收的几种常见算法)
JAVA GC 是JAVA虚拟机中的一个系统或者说是一个服务,专门是用于内存回收,交还给虚拟机的功能。 JAVA语言相对其他语言除了跨平台性,还有一个最重要的功能是JAVA语言封装了对内存的自动回收。俗称垃圾回收器。所以有时候我们不得不承认&#…...
你还不会用CAD一键布置停车位?赶紧学起来!
在设计CAD建筑图的过程中,你还在一个一个地画停车位吗?那未免也太低效了吧!今天,小编用浩辰CAD建筑软件来教大家一键布置停车位,赶紧学起来吧! 浩辰CAD建筑软件是行业应用最广泛的创新型建筑设计专业软件&…...
【MySQL之MySQL底层分析篇】系统学习MySQL,从应用SQL语法到底层知识讲解,这将是你见过最完成的知识体系
文章目录MySQL体系结构MySQL存储结构(以InnoDB为例)MySQL执行流程(以InnoDB为例)1. 数据写入原理2. 数据查询原理MySQL存储引擎1. 为什么需要不同的存储引擎2. 如何为数据指定不同的存储引擎,数据粒度又是多少3. MySQL…...
单核CPU是否有线程可见性问题?
本文仅是本人对问题的思考记录,并没有实操验证,有误请大家评论指出。 今天见到了一个经典的问题,单核CPU是否有线程可见性问题,学完操作系统应该可以直接回答,不会有线程安全问题。但如果结合JVM虚拟机来进行分析&…...
MyBatis 架构介绍
MyBatis 架构介绍MyBatis 架构图MyBatis 所解决的 JDBC 中存在的问题引用MyBatis 架构图 mybatis 配置:mybatis-config.xml,此文件作为 mybatis 的全局配置文件,配置了 mybatis 的运行环境等信息。另一个 mapper.xml 文件即 sql 映射文件,文件…...
加密算法---RSA 非对称加密原理及使用
加密算法---RSA 非对称加密原理及使用一 非对称加密原理介绍二 加密解密测试2.1 加密解密工具类2.2 测试一 非对称加密原理介绍 非对称加密算法中,有两个密钥:公钥和私钥。它们是一对,如果用公钥进行加密,只有用对应的私钥才能解…...
MySQL-查询语句
数据库管理系统的一个最重要的功能就是数据查询,数据查询不应只是简单查询数据库中存储的数据,还应该根据需要对数据进行筛选,以及确定数据以什么样的格式显示。MySQL提供了功能强大、灵活的语句来实现这些操作。下面是通过help帮助查看到的s…...
【算法】【数组与矩阵模块】求数组中需要排序的最短子数组长度
目录前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本思考感悟写在最后前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识! 问题介绍 …...
centos安装Anaconda3
目录一、参考二、Anaconda简介1、用途2、关于anaconda三、下载安装1、下载2、安装anaconda3、配置环境遍历4、测试配置结果5、设置显示前缀一、参考 在centos上安装Anaconda 最新Anaconda3的安装配置及使用教程(附图文) 二、Anaconda简介 一句话&…...
【微信小程序】-- WXML 模板语法 - 列表渲染 -- wx:for wx:key(十二)
💌 所属专栏:【微信小程序开发教程】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...
【Linux】Linux中gcc/g++的使用
本期主题:程序的编译过程和gcc/g的使用博客主页:小峰同学分享小编的在Linux中学习到的知识和遇到的问题小编的能力有限,出现错误希望大家不吝赐🍁 1.背景知识 预处理(进行宏替换,去注释,头文件的…...
【Spring Cloud Alibaba】(五)Dubbo启动报错?一直重连报错?你值得学习的是排查问题的方法
系列目录 【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战 【Spring Cloud Alibaba】(二)微服务调用组件Feign原理实战 【Spring Cloud Alibaba】(三)OpenFeign扩展点实战 源码详解 【Spri…...
adb命令的使用
命令 连接机顶盒 adb connect [机顶盒ip]查看已连接设备 adb devices断开某个机顶盒的连接 adb disconnect [机顶盒ip] or adb disconnect [虚拟机名称]断开所有设备连接 adb disconnect获取 root 权限 adb root挂载文件系统 adb remount当想往移动设备端 push 文件时显…...
springBoot自定义参数类型转换器
springBoot允许用户自定义转换器,以处理自定义请求参数协议。 方式一:通过实现接口:WebMvcConfigurer 并重写方法的形式。 Configuration public class BootConfig implements WebMvcConfigurer {/*** 自定义参数转换*/Overridepublic voi…...
OA系统在企业中的应用你知道哪些?
随着人工智能技术的不断发展,企业中的OA系统(Office Automation System)正在逐渐得到广泛应用。OA系统是一种集成了多种功能的信息化工具,能够帮助企业实现办公自动化、信息管理、决策支持等多种功能。本文将从OA系统在企业中的应…...
JAVA中,ArrayList 的扩容机制,含案例
JAVA中,ArrayList 的扩容机制,含案例 在 Java 中,ArrayList 是一个动态数组,它可以根据需要自动增长。当 ArrayList 中的元素数量超过其初始容量时,它会重新分配一个更大的内部数组,然后将现有元素复制到新…...
供应链的有效管理,分析指标有哪些
对于企业而言,供应链是一个很复杂的、体系化的生态系统,从原材料、到供应商、到生产、仓库、物流,最后到达经销商或者最终客户那里,这个链条很长。相关的分析指标也有很多,在这些指标里面也有非常多可以扩展、延申的内…...
嵌入式环境配置—VMware 软件安装和虚拟机的创建
目录 一、VMware软件的安装 二、虚拟机的创建 三、Linux操作系统的安装 VMware软件的安装 为什么要虚拟机? 嵌入式Linux开发需要在Linux系统下进行,我们选择了Ubuntu。 1.双系统安装 有问题,一次只能使用一个系统。Ubuntu基本只做编译用。需求&…...
阿里前端二面经典手写面试题汇总
实现类的继承 实现类的继承-简版 类的继承在几年前是重点内容,有n种继承方式各有优劣,es6普及后越来越不重要,那么多种写法有点『回字有四样写法』的意思,如果还想深入理解的去看红宝书即可,我们目前只实现一种最理想…...
【Eye】Fake News Reading on Social Media: An Eye-tracking Study
Fake News Reading on Social Media: An Eye-tracking Study Abstract 在网上传播假新闻(以及一般的虚假信息)最近被认为是威胁整个社会的一个主要问题。这种传播在很大程度上是由于新的媒体形式,即社交网络和在线媒体网站。研究人员和从业…...
从HIDL到HAL3:手把手拆解Android相机Provider进程的通信与数据流转
Android相机架构深度解析:从HIDL到HAL3的数据流转与性能优化 在移动影像技术快速迭代的今天,Android相机系统的架构设计直接影响着成像质量与用户体验。作为连接应用层与硬件层的核心枢纽,Camera Provider进程通过HIDL接口与Camera Service通…...
三步掌握MarkDownload:将网页内容高效转换为结构化笔记
三步掌握MarkDownload:将网页内容高效转换为结构化笔记 【免费下载链接】markdownload A Firefox and Google Chrome extension to clip websites and download them into a readable markdown file. 项目地址: https://gitcode.com/gh_mirrors/ma/markdownload …...
VINS-Mono跑EUROC数据集实战:如何解读Rviz可视化结果与评估轨迹精度?
VINS-Mono EUROC数据集实战:Rviz可视化与轨迹精度评估全解析 当你第一次在Rviz中看到VINS-Mono处理EUROC数据集生成的复杂点云和轨迹时,那种既兴奋又困惑的感觉我完全理解。作为一款开源的视觉惯性里程计(VIO)系统,VINS-Mono在无人机、移动机…...
基于OpenTelemetry的LLM应用可观测性实践:从黑盒到透明化
1. 项目概述:当LLM应用遇见可观测性如果你正在开发或运维基于大语言模型(LLM)的应用,那么你一定遇到过这样的场景:用户反馈“AI回答得不对”,或者“响应突然变慢了”。当你一头扎进日志和监控系统ÿ…...
历史周期律的动力学本质:集体意识场视角下的文明演进规律
引言 历史周期律——王朝兴替、文明盛衰、社会变革的波浪式重复——是人类文明最令人困惑又最无法回避的现象。从司马迁的“天下大势,分久必合,合久必分”,到汤因比的文明挑战-回应理论,无数先贤试图揭示这一规律的底层逻辑。然而…...
ARM PB11MPCore USB与DVI接口设计与信号完整性分析
1. ARM PB11MPCore接口架构解析PB11MPCore作为ARM经典的嵌入式开发平台,其外设接口设计体现了工业级嵌入式系统的典型特征。我们先从整体架构入手,理解USB和DVI接口在系统中的位置。1.1 系统级接口布局开发板采用前后面板分离设计,关键接口分…...
DSP架构设计与低功耗优化关键技术解析
1. DSP架构基础与性能挑战数字信号处理器(DSP)与传统微控制器在架构设计上存在本质差异。微控制器主要面向控制任务——处理输入数据、做出决策并调整输出设备状态,而DSP的核心使命是维持连续数据流的高效处理。这种差异直接体现在硬件架构的…...
数据流编排工具 diflowy:从核心概念到实战部署全解析
1. 项目概述:当“绿色”遇上“数据流编排” 最近在开源社区里,一个名为 green-dalii/diflowy 的项目引起了我的注意。乍一看这个名字, green-dalii 像是一个开发者或组织的标识,而 diflowy 则巧妙地融合了“data flow”&…...
Hermes模型优化实战:量化、剪枝与蒸馏技术全解析
1. 项目概述:一个为Hermes模型量身定制的“武士刀”如果你最近在关注大语言模型(LLM)的微调领域,特别是那些追求极致推理速度和响应效率的模型,那么“Hermes”这个名字你一定不陌生。它通常指代一系列基于Llama、Mistr…...
微博图文视频批量采集软件用户手册
目录 系统介绍 安装与配置 功能使用说明 常见问题 日志查看 系统介绍 本系统是一款微博内容采集与媒体处理工具,主要功能包括: 采集微博内容(图文、视频) 视频裁剪与去水印 AI标题优化 文件分类保存 自动抽帧 安装与配…...
