jvm垃圾收集器与三色算法

2023-11-10 10:40

本文主要是介绍jvm垃圾收集器与三色算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先要写垃圾收集算法(针对堆空间)

 垃圾收集算法包含 分代收集理论、复制算法、标记整理算法、标记清除算法分代收集理论是 堆空间分为新生代老年代  分代收集理论就是判断新生代用什么垃圾回收器老年代用什么垃圾回收器 
复制算法、标记整理算法、标记清除算法 根据分代收集理论从而告诉用什么垃圾收集器(垃圾收集器实现了复制算法、标记整理算法、标记清除算法) 这三个其中一个复制算法 一般针对新生代 比如新生代的一块内存 它会把这个内存空间分成两半一般是用来存储对象另一半是未使用的空间当存储对象的那半空间满了就会触发minor GC  把那半存储对象的内存空间进行回收 然后把存活的对象放到未使用的那半内存中 它还会把内存做一下整理 下一次minor GC时也是这样 就是来回复制标记清除算法  是做gc时会用gc root标记非垃圾对象  标记完就把没有标记的对象清除 它会有缺点 如果内存很大那么它标记的时间就会很长  清除垃圾对象之后还会留下内存碎片   一般用在老年代标记整理算法  是做gc时会用gc root标记非垃圾对象  标记完就把这些非垃圾对象向上移动到那些垃圾对象的内存空间往上 也就是做了一个从新赋值的操作 但是如果垃圾对象在内存空间的最后一行那么就需要手动的清理垃圾收集器(后面会有张垃圾收集器的图谱) 就是实现了上面说复制算法、标记清除算法、标记整理算法Serial(读音谁瑞要)(新生代使用)---Serial Old(老年代使用)---CMS(老年代使用) // 这里表示新生代垃圾回收器可以跟哪些老年代垃圾回收器做配合ParNew(读音怕牛)(新生代使用) --- Serial Old(老年代使用)--- CMS(老年代使用)// 这里表示新生代垃圾回收器可以跟哪些老年代垃圾回收器做配合Parallel(读音拍累瑞要)(新生代使用)--- Parallel Old(老年代使用)--- Serial Old(老年代使用)// 这里表示新生代垃圾回收器可以跟哪些老年代垃圾回收器做配合当然垃圾回收器还有好的这里 后续会在写几个 以上的垃圾回收器在JDK1.8算是最稳定的了

Serial收集器(-XX:+UseSerialGC年轻代 -XX:+UseSerialOldGC老年代)

Serial(串行)收集器是最老的一个 它是一个单线程的收集器 单线程的意思不是只用一个垃圾线程去收集垃圾而是当它做垃圾收集的时候会把其他所以线程的工作停止(Stop The World 读音死到破 泽 我的)直到它垃圾收集结束 它新生代使用复制算法 老年代使用标记整理算法(后面会有张关于它的图) 现在一般都使用JDK1.8它的作用主要就是给CMS收集器做后备方案Parallel Scavenge(读音怕累瑞要 死噶为吃)收集器(-XX:UseParallelGC年轻代-XX:UseParallelOldGC老年代) JDK8默认使用这个收集器其实就是Serial收集器的多线程版本 它的默认线程数与cpu线程数一样(可以通过-XX:ParallelGCThreads制定线程数 一般不要修改) 这个收集器关注点是吞吐量(cpu执行效率)CMS等垃圾收集器关注点为用户线程停止的时间   新生代使用复制算法 老年代使用标记整理算法ParNew收集器(-XX:UseParNewGC) 这个收集器跟Parallel收集器很类似 区别就是ParNew可以跟CMS收集器做配合而Parallel收集器不可以  ParNew收集器是一个新生代的收集器  使用复制算法CMS收集器(-XX:UseConcMarkSweepGC)使用标记清楚算法(老年代收集器)后面会有图CMS全称(Concurrent Mark Sweep 读音炕卡伦特 猫可 死为铺)它是以stw时间最短作为目标 它第一次实现了让用户线程跟垃圾线程同时工作  它主要有五个 初始标记、并发标记、重新标记、并发清理、并发重置初始标记会stw 主要标记了 A a = new A() a指向new A() 而new A()中的那些引用类型的成员变量还没有标记  会stw并发标记在初始标记的基础上继续往下标记 开始找new A()中那些引用类型的成员变量 (gc root)不会stw重新标记 因为在并发标记时 是跟用户线程同时工作 可能会出现因为用户线程导致那些本来是垃圾的对象变成不是垃圾了把它又重新赋值了  那些不是垃圾的变成垃圾  并发标记就是在这基础上再检查一遍并做出相应的处理 会stw并发清除 这一步就开始根据重新标记的结果清理垃圾 如果有新的对象产生它会把这个对象标记为黑色 不会stw并发重置 是把那些标记的gc root根节点取消标记 不会stwCMS会有一些问题在并发标记时会有垃圾对象未标记 而造成无法清理这个垃圾或者一些垃圾 这种垃圾称为“浮动垃圾” 它的解决办法就是等下次gc时再做处理 它还会跟跟用户线程抢夺cpu时间片 这个其实不算是问题但是也有 还有CMS采用的是标记清除算法 那么它就会造成大量的内存碎片 这个问题可以通过(-XX:UseCMSComPactAtFullCollection这个jvm指令让它在标记清除完之后做内存碎片的整理)  执行过程中会有不确定的因素 会存在这次gc还没完成又触发gc 这时会触发CMS的并发失败concurrent mode failure(读音炕卡伦特 猫到 fai要也) 机制如果触发了这个机制那么就会进入Stop The Wrod 并换成serial old收集器做垃圾回收工作  因为serial old收集器是单线程 它的效率是非常低的 所以一定不能让它出现并发失败问题 这个问题可以通过(-XX:CMSInitiatingOccupancyFraction 这个指令表示老年代的内存达到多少让它触发gc默认百分之92 具体大小要通过分析系统进行设置)

CMS的相关核心参数

  1. -XX:+UseConcMarkSweepGC:启用cms

  2. -XX:ConcGCThreads:并发的GC线程数

  3. -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)

  4. -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次

  5. -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)

  6. -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整

  7. -XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少老年代对年轻代的引用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段

  8. -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW9. -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW;亿级流量电商系统如何优化JVM参数设置(ParNew+CMS)

垃圾收集底层算法实现

三色标记
在程序运行中并发标记会出现 多标、漏标的情况 多标就是把一个垃圾对象标记为非垃圾对象也就是浮动垃圾等下次gc再做处理即可 而漏标就是一个非垃圾对象没有被标记为非垃圾对象 这就是一个很严重的问题了一个对象正在用 而垃圾收集器把它给清理了是一个很严重的问题

三色标记 这里用黑色、灰色、白色黑色表示已经被gc root扫描完的对象灰色表示gc root扫描了但是还没扫描完白色表示未被gc root扫描的对象public class A{ B b = new B(); C c = null;}public class B{ D d = new D();C c = new C();}public class C{}public class D{}A a = new A()C c = a.b.c;a.c = a.b.c;a.b.c = null;以上是故事背景 CMS收集器环境下 下面说的都是假设一个故事这里表达的什么是漏标 就是当A a = new A()这个以及做完gcroot 标记为黑色 可以扫描完一定有做了并发标记 并发标记跟用户线程一起的也就是说 C c = a.b.c;这样代码下面的代码也在执行 可以看到a.c=a.b.c然后又给a.b.c=null; 然后上面说扫描A扫描完了 但是这个扫描完了定义是指A类中的扫描了b跟c是否有指向一个对象实例 但是这个对象实例还没进入类中扫描 也就是B类中的c跟d 这种情况A类是标记为黑色因为它里面的变量以及扫描完了 B类假设扫描到了d还没扫描c 会把B标记为灰色 这时用户线程把a类中的c变量给赋值了赋值的为a类中的b类中的c 下面又把这个c给赋值为null A标记为黑色对象了无法再被扫描了这就是漏标的情况 B类是灰色在重新标记时会扫描   漏标解决方法增量更新 原始快照

漏标 -读写屏障 (这是一个概念)

增量更新 黑色对象一旦新插入了指向白色对象的引用时它就会变成灰色对象

原始快照 就是当灰色对象删除了一个指向白色对象的引用时 会把这个引用记录下来 确保不会被删除 就算是垃圾就让它变成浮动垃圾 在下次gc时处理

写屏障 在java HotSpot VM(java源码)中 在赋值操作前后给它做一些什么什么操作 就是有两个队列一个赋值操作前的队列一个赋值操作后的队列

读屏障 就是在读取这个变量的内存地址时前后做些什么事

CMS 处理漏标的方案 写屏障+增量更新

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

这篇关于jvm垃圾收集器与三色算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/382129

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第