Java常见GC算法_垃圾收集器及内存分配_G1垃圾收集器

常见GC算法

  • 引用计数法: 每个对象都有一个计数器, 对象被引用一次, 计数器+1, 当对象引用失败一次. 计数器-1, 当对象计数器等于0, 说明对象没有被应用, 就可GC
优:  运行过程中, 可随时检查对象计数器, 进行GC, 且GC过程, 应用无需暂停, 执行速度快(单个对象GC不会影响其他对象), 内存不足, OOM
缺: 存在循环引用问题(A引用B, B引用A, A=null, B=null. A,B永远不会GC), 随时都在GC, 占用CPU
  • 标记清除: 先标记( 从root进行可达性分析, 标记被引用的对象), 再清除(清除那些没被引用的对象)
    在这里插入图片描述
优; 解决循环引用问题
缺: 效率低下, 需要遍历所有对象, 碎片化严重, 清理出来的内存不连续, 当new大对象时, 容易爆OOM 
  • 标记压缩: 标记需要回收的区域, 进行回收, 将碎片化的空间进行压缩
    在这里插入图片描述
优: 解决标记清除的碎片化问题
缺: 需要移动内存位置, 效率降低
  • 复制算法: 将空间一分为二(只使用其中一块空间进行存储), 进行清除的时候, 将存活对象复制到另外一块空间, 原本的空间全部清除, 解决移动内存问题
    在这里插入图片描述
优: 解决标记清除存在的内存移动问题
缺: 对空间的浪费较为严重, 不适用内存空间垃圾较少的情况

复制算法在JVM年轻代的应用

在这里插入图片描述

1. GC开始前, 对象分布于Eden, s0区, s1区为空
2. GC开始, Eden中的存活对象全部复制到s1中, s0区中存活对象根据他们的年龄值决定去向使用-XX:MaxTenuringThreshold设置年龄阈值, 超过该阈值, s0中对象移到老年代, 未达到, 对象则移动到s1中
3. GC完成, 清空Eden, s0区域, s0与s1交换角色, 重复步骤1, 直到"s1"被填满, 然后将"s1"中对象全部移到老年代中
优: 垃圾对象较多时, 效率高, 无碎片化
缺: 垃圾较少, 不适用, 如:老年代, s0/s1一个时刻只能使用其中一块, 内存使用率低

分代算法: 年轻代采用复制清除, 老年代使用标记清除/压缩

垃圾收集器及内存分配

  • 串行垃圾收集器: GC过程, 只有一个线程工作, 且应用要停止运行(Stop-the-world), 等待GC完成.
/*** 测试GC收集器* @author regotto*/
public class GcTest {public static void main(String[] args) {ArrayList<Object> objects = new ArrayList<>();while (true) {if (System.currentTimeMillis() % 2 == 0) {//产生大量废弃对象objects.clear();} else {for (int i = 0; i < 10000; i++) {Properties properties = new Properties();properties.put("key:" + i, "value:" + System.currentTimeMillis());objects.add(properties);}}try {Thread.sleep(new Random().nextInt(100));} catch (InterruptedException e) {e.printStackTrace();}}}
}

设置VM Optional: 使用串行GC器, 打印GC细节
在这里插入图片描述
运行结果如下:

在这里插入图片描述
日志解读(使用第一行数据):

GC: 年轻代GC;	Full GC: 所有空间全部GC
DefNew: 使用串行GC器
4416k -> 512k(4928k): GC前年轻代对象占4416k空间, GC年轻代对象占512k空间, 总共4928k空间
0.0019950secs: GC花费时间
7318k -> 3975k(15872k): 堆空间GC情况
  • 并行垃圾回收器: 在串行GC的基础上, 变为多线程进行GC操作(存在Stop-the-world), 其余与串行GC一样
    • ParNew垃圾收集器
      只能在年轻代工作(只是将串行GC变为并行GC), 使用-XX:+UseParNewGC设置, 老年代依旧采用串行GC
      在这里插入图片描述
      测试代码在上一个代码的基础上修改VM options
      运行过程中, 发现相比于SerialGC, ParNew在GC上存在一定的提升
    • ParallelGC垃圾收集器
      与ParNew一样, 新增多个与吞吐量相关的参数, 操作更加灵活
-XX:+UseParallelGC 年轻代使用ParallelGC垃圾回收器,老年代使用串行回收器。
-XX:+UseParallelOldGC 年轻代使用ParallelGC垃圾回收器,老年代使用ParallelOldGC垃圾回收器。 
-XX:MaxGCPauseMillis 设置最大的垃圾收集时的停顿时间,单位为毫秒 需要注意的是,ParallelGC为了达到设置的停顿时间,可能会调整堆大小或其他 的参数,如果堆的大小设置的较小,就会导致GC工作变得很频繁,反而可能会 影响到性能。 该参数使用需谨慎。 
-XX:GCTimeRatio 设置垃圾回收时间占程序运行时间的百分比,公式为1/(1+n)。 它的值为0~100之间的数字,默认值为99,也就是垃圾回收时间不能超过1% 
-XX:UseAdaptiveSizePolicy 自适应GC模式,垃圾回收器将自动调整年轻代、老年代等参数,达到吞吐量、 堆大小、停顿时间之间的平衡。 一般用于,手动调整参数比较困难的场景,让收集器自动进行调整。

在这里插入图片描述
测试代码与前一个一样, 只修改VM options, 运行结果如下:
在这里插入图片描述

  • CMS垃圾处理器
    CMS(Concurrent Mark Sweep): 针对老年代(对老年代GC进行改进), 使用标记清除算法, -XX:UseConcurrentMarkSweepGC设置.
    执行过程如下:
    在这里插入图片描述
InitialMarking: 标记root, 出现Stop-the-world
Marking: 标记对象, 与应用线程同时运行
preclean: 预清理, 与应用线程同时运行
finalMarking: 再次标记, 由于与应用线程同时运行, 前期的标记并不能解决问题, 此过程出现Stop-the-world
sweeping: 并发清除, 与应用线程同时运行
resizing: 调整堆大小, 清理碎片, 压缩空间
resetting: 重置, 等待触发下一次CMS, 与用户线程同时运行

在这里插入图片描述
程序打印的日志也是按照上面的流程, 程序运行结果如下:
在这里插入图片描述

G1垃圾收集器(jdk1.7使用)

G1取消传统的新生代, 老年代物理划分, 将内存空间变为若干个区域, 每个区域包含逻辑上的新生代, 老年代. G1存在YoungGC, MixedGC, FullGC, 在不同的条件下触发

优: 每一块区域存在多种状态(Old, Eden, Humongous, Survivor)解决碎片化问题, 即使在正常处理过程中, 都能解决内存压缩问题

在这里插入图片描述

G1的YoungGC

Eden区空间耗尽触发, EdenGC, Eden中数据移动到Survivor区(Survivor满了, 数据移动到新的Survivor区, 部分数据移动到Old区), 部分数据移动到Old区, 当前Eden清空, 变为未使用区
在这里插入图片描述

RememberSet(记忆集合)

RememberSet解决新生代寻找根对象的问题, 每一个区域初始化都生成一个RememberSet, 该集合保存其他对象引用"我"的记录, 扫描RememberSet就能得出对象之间的引用关系, 而不再需要对新生代, 老年代中所有对象进行扫描.
在这里插入图片描述

G1的MixedGC

为避免堆内存被耗尽, JVM启动MixedGC, 回收所有的Young区, 回收部分Old区(MixedGC不是FullGC).
使用-XX:InitiatingHeapOccupancyPercent=n(老年代占整个堆大小百分比阈值) 决定MixedGC什么时候触发
MixedGC分为2个步骤: 全局并发标记(前5个步骤), 拷贝存活对象(第6个步骤)
在这里插入图片描述

G1相关参数

-XX:+UseG1GC 使用 G1 垃圾收集器 
-XX:MaxGCPauseMillis 设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到),默认 值是 200 毫秒。
-XX:G1HeapRegionSize=n 设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间。目标是根 据最小的 Java 堆大小划分出约 2048 个区域。 默认是堆内存的1/2000。
-XX:ParallelGCThreads=n 设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑 处理器的数量相同,最多为 8。
-XX:ConcGCThreads=n 设置并行标记的线程数。将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。
-XX:InitiatingHeapOccupancyPercent=n 设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%。

G1日志输出参数

‐XX:+PrintGC 输出GC日志
‐XX:+PrintGCDetails 输出GC的详细日志 
‐XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式) 
‐XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013‐05‐ 04T21:53:59.234+0800) 
‐XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息 
‐Xloggc:../logs/gc.log 日志文件的输出路径

测试

在这里插入图片描述
代码运行完毕自动将GC日志输入到项目下的gc.log中
使用GC Easy进行分析(http://gceasy.io)
将gc.log上传该网站, 就能进行GC分析, 获取分析报告

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

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

相关文章

是应该有点兴奋剂刺激下

不知道你有没有发现一个问题&#xff0c;发现身边的很多人工资很高&#xff0c;但是好像总还是缺点什么&#xff0c;总是对生活提不起兴趣&#xff0c;似乎对任何事情都失去热情&#xff0c;每天拿着手机&#xff0c;点来点去&#xff0c;每天都在抱怨&#xff0c;每天都好像在…

你应该知道为什么需要内核

不知道大家想过这个问题没有&#xff1f;为什么要有内核&#xff1f;如果没有内核有怎么样呢&#xff1f;因为有了 unix 内核&#xff0c;有了 minix 后面又有了 Linux 内核&#xff0c;内核这个思想越来越根深蒂固&#xff0c;估计没学什么计算机知识的人都能侃出点所以然来。…

2019深圳入户攻略

我上次说了&#xff0c;等我把户口办好了&#xff0c;我就把攻略写出来&#xff0c;给大家一个参考&#xff0c;今天刚好是我最后的一个步骤&#xff0c;去派出所把身份证给办了&#xff0c;好了&#xff0c;我以后就是深圳人了&#xff0c;来深圳快十年了&#xff0c;现在才真…

NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径

NIO之ByteBuffer与Channel 传统IO:byte[] < inputStream < 文件 > outputStream > byte[] NIO:文件 > inputChannel <> buffer <> outputChannel > 文件文件 < inputChannel <> outputChannel > 文件文件复制, 并测试ByteBuffer常用…

mp4 拍摄时间如何看_时间不多了,如何备考期末最有效?这些复习技巧,看了你就会了...

再过不到一个月就要过年了&#xff0c;虽然天气越来越冷&#xff0c;但是有阻挡不了年度大戏“期末考”的前进步伐&#xff0c;尤其是对于紧张复习之中的高考备考生而言&#xff0c;高三第一学期的期末考就可以算是对自己第一轮复习的一个检验&#xff0c;如果成绩不理想&#…

vue实战学习第二天

1.怎么运行别人的项目 步骤一&#xff1a;搭建脚手架&#xff1a;npm i -g vue-cli 步骤二&#xff1a;vue init webpack 不要一直默认回车&#xff0c;去除一些不必要的依赖&#xff0c;减少代码的编写难度 步骤三&#xff1a;下载依赖的文件 npm i &#xff08;可能有些人会…

Netty之自定义RPC

需求分析 使用netty实现方法远程调用, 在client调用本地接口中方法时, 使用反射进行远程调用, server执行完结果后, 将执行结果进行封装, 发送到client RPC调用模型: 1. 服务消费方(client)以本地调用方式调用服务 2. client stub 接收到调用后负责将方法、参数等封装成能够…

samba 服务器搭建

为什么要搭建samba 服务器我在 windows 下安装了个虚拟机&#xff0c;然后想两边同步下资料&#xff0c;原来虚拟机是可以共享文件的&#xff0c;可是不知道什么见鬼了&#xff0c;就是不行&#xff0c;没办法了&#xff0c;我只好拿出我的杀手锏&#xff0c;安装 samba。这个在…

一直想说的,技术职业化

最近后台有人一直跟我说&#xff0c;为什么不好好写一篇技术比较强的文章&#xff0c;说实话&#xff0c;最近时间比较紧张&#xff0c;早上 8 点出门&#xff0c;晚上12点左右到家。刚好今天整理了一个不错文章的列表&#xff0c;明天发出来&#xff0c;希望给学习的同学们有点…

MyBatis初级入门及常见问题

入门案例 创建maven工程 项目目录结构: 首先在maven的pom.xml导入Mybatis和MySQL的依赖坐标: <dependencies><!--Junit测试依赖--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</…

读书笔记:Information Architecture for the World Wide Web, 3rd Edition 北极熊 第一部分 1-3...

Introducing Information Architecture 信息架构简介 Chapter 1 Defining Information Architecture 信息架构的意义&#xff08;我们盖房子&#xff0c;之后&#xff0c;房子影响我们&#xff09; A DefinitionTablets, Scrolls, Books, and Libraries 石板、卷轴、书籍&#…

Mybatis执行流程分析_自定义简易Mybatis框架

自定义简易Mybatis框架 Mybatis执行流程分析 Mybatis代码编写流程: Mybatis配置文件加载过程: 需求分析及技术概述 根据上述的功能结构图, 得出如下需求: 1. 需要具有配置文件加载模块. 2. 支持使用构建者进行SessionFactory构建. 3. 支持使用工厂模式构建Session对象. 4.…

给大家推荐一个优质Linux内核技术公众号-Linux阅码场

作为一个Linux 技术公众号的作者&#xff0c;我觉得有义务推荐优秀的公众号&#xff0c;推广内容&#xff0c;希望对大家的学习有所帮助~Linux阅码场是一个专注Linux内核和系统编程与调试调优技术的公众号&#xff0c;它的文章云集了国内众多知名企业一线工程师的心得。无论你工…

图数据库_ONgDB图数据库与Spark的集成

快速探索图数据与图计算图计算是研究客观世界当中的任何事物和事物之间的关系&#xff0c;对其进行完整的刻划、计算和分析的一门技术。图计算依赖底于底层图数据模型&#xff0c;在图数据模型基础上计算分析Spark是一个非常流行且成熟稳定的计算引擎。下面文章从ONgDB与Spark的…

2019 高考填报志愿建议

2019 高考填报志愿建议1、城市很关键&#xff0c;在大城市上学和小地方上学会有很大的不同&#xff0c;现在很多毕业生毕业后会往北上广深跑&#xff0c;很多原因是因为这里的就业机会多&#xff0c;薪资比内地好太多了&#xff0c;如果你大学就能在这样的地方上学&#xff0c;…

韦东山:闲鱼与盗版更配,起诉到底绝不和解!

之前很多人问&#xff0c;我和韦老师是什么关系&#xff0c;我们是本家人&#xff0c;至于更深的关系&#xff0c;我也不知道&#xff0c;这次事件受老师委托&#xff0c;帮忙发文支持&#xff0c;看到的朋友&#xff0c;也希望给予转发支持&#xff0c;感激不尽~大学的时候&am…

Windows下搭建FTP服务器

一、什么是ftp? FTP 是File Transfer Protocol&#xff08;文件传输协议&#xff09;的英文简称&#xff0c;而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时&#xff0c;它也是一个应用程序&#xff08;Application&#xff09;。基于不同的操作系统有不…

Redis常见数据类型_Redis通用指令

Redis常见数据类型 redis本身就是一个Map结构, 所有数据都采用key:value的形式, redis中的数据类型指的是value的类型, key部分永远是字符串 string(类似Java String) string基本操作: set key value //存储数据 get key value //获取数据 del key value //删除数据 mset …

我关注的学习公众号

在这个激烈竞争的社会&#xff0c;职场上还有“一招鲜”么&#xff1f;面对35岁的“魔咒”&#xff0c;提升自我的路很多&#xff0c;学习是其中最为捷径的一条。只有不断学习新知识&#xff0c;才能保持进步。今天为大家整理了8个公众号&#xff0c;分别为各个领域的佼佼者&am…

如何让开关打开_安卓手机如何打开USB调试模式

点击上方“手机互联” 关注我吧&#xff01;什么是USB调试模式&#xff1f;USB调试模式是 安卓手机提供的一个用于开发工作的功能。使用该功能可在设备和安卓手机之间复制数据、在移动设备上安装应用程序、读取日志数据等等。默认情况下&#xff0c;USB 调试模式是关闭的&#…