热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发中的垃圾回收算法

01、垃圾回收的过程在分代收集算法下:当JV

01、垃圾回收的过程

在分代收集算法下:


  • 当JVM内存不足时,就会触发年轻代得GC;


  • 首先,会通过可达性分析来判断哪些对象垃圾对象;


  • 接着,将这些对象放入死亡队列,进行对象得死亡判断与回收;


如果上述GC后,内存还不够。就会触发老年代GC。如果内存还不够,就会触发Full GC。

02、三种GC

(1)Minor GC


  • 在年轻代进行垃圾回收;


  • 这种GC速度快、效率高、回收率高;


  • 当程序内存不足时,触发。


(2)Major GC


  • 在老年代进行垃圾回收;


  • 这种GC速度慢、效率慢、回收率低;


  • 当Minor GC后,还是没法满足后,就会触发Major GC;


(3)Full GC


  • 回收整个堆的对象


  • 当Minor GC、Major GC都没满足要求后,才会进行的GC



Full GC在java7、8对于方法区的区别。


一、如何确定垃圾


01、引用计数

开发中的垃圾回收算法 - 文章图片
这里认为一个对象的引用没有被任何人持有的话,这个对象就是垃圾。
当一个对象被赋值给其他人时,其引用计数就会+1。当引用对象不再引用它时,其引用计数就会-1。当GC发生时,就会认为这个对象是可以清除得。

1、优缺点分析
引用计数得优点在于快。当一个对象得引用计数为0时,就可以被GC了,不需要进行可达性分析;
缺点在于无法处理循环引用,如上图红色部分。

现代JVM已经不使用这种方法


02、可达性分析

可达性分析会设置某些对象是GC Root,凡是某个对象通过引用链可以达到GC Root对象得话,就认为这个对象是活对象。反之,认为它是垃圾对象。
1、java中哪些对象是GC Root对象?


  • 所有得Thread对象


  • 栈帧中得局部变量表


  • 方法区得静态成员


  • JNI持有得引用


  • Monitor


  • 其他JVM持有得GC Root:比如说:如果年轻代在GC时,老年代里面得所有对象都是GC Root。



参考信息


二、对象得死亡判定

开发中的垃圾回收算法 - 文章图片
通过可达性分析后,将不可达对象放入死亡队列;垃圾回收器调用这些不可达对象得finalize方法最终判断是否回收他。
也就是说我们可以通过覆盖finalize方法,让这个对象永远都不会垃圾回收。但是非常不推荐使用。

三、垃圾回收算法

java中得gc不仅要回收对象,还要压缩空间。压缩空间目的是让程序有更多连续内存使用,减少内存的碎片化。
开发中的垃圾回收算法 - 文章图片

GC分代收集算法


01、分代假设

研究发现,JVM中大部分对象都是用完后,立马就不再使用了。
开发中的垃圾回收算法 - 文章图片

02、内存分代

开发中的垃圾回收算法 - 文章图片
JVM将对象分为3种年纪:


  • 年轻代:Young



    • Eden(TLABs)


    • Survivor



  • 老年代:Tenured(Old)


  • 永久代:PermGen/Metaspace



(1)年轻代垃圾回收

开发中的垃圾回收算法 - 文章图片


  • 当Eden内存不够时,会触发年轻代GC。此时,Eden内对象要不然作为垃圾回收了,要不然就进入S1区;


  • 此时S区中对象得年龄会加1,并将S1区对象汇合到S2;


  • 汇合后,凡是对象超过15岁,就可以进入老年代了;


这里会涉及到一个GC调优得现象:对象过早提升。
就是由于Eden区域过小,导致每次创建大对象时,Eden区域内存不够,只能在老年代上分配。这时候,就需要将Eden内存大小调大一点。

(2)老年代垃圾回收

开发中的垃圾回收算法 - 文章图片
老年代垃圾回收时,只会将垃圾对象清除掉,然后合并一下碎片空间。



相关知识

1、GC的三种实现过程


Mark-and-Sweep:标记清除

开发中的垃圾回收算法 - 文章图片

Mark-Sweep-Compact:标记、清除、压缩

开发中的垃圾回收算法 - 文章图片

Mark-and-Copy:标记、拷贝

开发中的垃圾回收算法 - 文章图片

2、 GC的Mark阶段


Stop The World(STW)

STW是指所有应用线程都到达safe point点时,为了GC工作需要,会停止所有的应用线程。这时候,GC线程就可以开始扫描GC Roots。

这样直观的感觉就是应用卡顿,这也是GC调优的关键指标。

注意:GC的停顿与堆大小无关,只与活对象大小有关。有时候增加堆大小不仅不能减少延迟,反而会增加延迟。

safe point


垃圾回收器

开发中的垃圾回收算法 - 文章图片

一、Serial GC:串行垃圾回收器

单线程串行GC:Serial、Serial Old
1、年轻代:Mark-Copy
2、老年代:Mark-Sweep-Compact
3、相关配置:


  • -XX:+UseSerialGC:开启Serial GC


  • -XX:+PrintGCDetails:开启打印GC详情


  • -XX:+PrintGCDateStamps:开启打印GC时间戳


  • -xx:+PrintGCTimeStamps:开启打印GC时间戳


4、应用介绍
(1)在JVM启动参数上如下参数

-XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps

-XX:代表这是一个非标准JVM参数,只在hotSpot虚拟机有效

+:开始开启

(2)GC日志的分析

# 时间戳 : GC花费的时间 2020-04-02T14:20:29.653+0800: 5.054: 
# GC开启的原因 GC开始的时间戳: [GC (Allocation Failure) 2020-04-02T14:20:29.653+0800: 5.054: 
# DefNew表示我们使用的串行垃圾回收器:回收前年轻代大小->回收后年轻代大小(年轻代总的大小),花费的时间[DefNew: 151750K->5184K(157376K), 0.0180036 secs] 
# 回收堆的大小 -> 回收堆的大小(堆的总大小),花费的时间162889K->24012K(506944K), 0.0180394 secs] # 时间:在用户模式下花费的时间,在系统模式下花费的时间,真实花费的时间[Times: user=0.02 sys=0.00, real=0.02 secs]

二、Paraller GC:并行垃圾回收器



  • 年轻代:Mark-Copy


  • 老年代:Mark-Sweep-Compact


使用多个线程并发标记清除。
包含的垃圾回收器:ParNew、CMS、ParallelScavenge、Parallel Old
并发垃圾回收器经历了俩个阶段:


  • 早期的时候,开发出ParallelScavenge、Parallel Old,分别回收年轻代和老年代


  • 后来又开发出:ParNew、CMS



三、Concurrent GC:并发垃圾回收器


CMS:Concurrent Mark Sweep

开发中的垃圾回收算法 - 文章图片
1、paraller vsConcurrent
并行、并发

2、优点
之前的垃圾回收器运行时,需要STW,而这个时间可能很长。CMS为了减少STW的暂停时间,就提出在部分时刻才需要所有应用线程停止,其他的时候应用线程和GC线程一样,一起工作。

3、缺点


  • CMS只能清除老年代,所以它需要搭配Serial、ParNew来清除年轻代。


  • CMS垃圾回收器只能实现Mark-Sweep,无法做到Compact,因为应用线程在跟GC线程一起运行的;


4、过程



    • 初始标记:GC roots直接引用


    • 并行标记:大多数的活对象


    • 重新标记:并发标记,因为上次并行走的时候,可能标记的不完全准确


    • 并行清理:





推荐阅读
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • 深入解析Spring Boot启动过程中Netty异步架构的工作原理与应用
    深入解析Spring Boot启动过程中Netty异步架构的工作原理与应用 ... [详细]
  • Hadoop平台警告解决:无法加载本机Hadoop库的全面应对方案
    本文探讨了在Hadoop平台上遇到“无法加载本机Hadoop库”警告的多种解决方案。首先,通过修改日志配置文件来忽略该警告,这一方法被证明是有效的。其次,尝试指定本地库的路径,但未能解决问题。接着,尝试不使用Hadoop本地库,同样没有效果。然后,通过替换现有的Hadoop本地库,成功解决了问题。最后,根据Hadoop的源代码自行编译本地库,也达到了预期的效果。以上方法适用于macOS系统。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • 在2015年1月的MySQL内核报告中,我们详细探讨了性能优化和Group Commit机制的改进。尽管网上已有大量关于Group Commit的资料,本文将简要回顾其发展,并重点分析MySQL 5.6及之前版本中引入的二进制日志(Binlog)对性能的影响。此外,我们还将深入讨论最新的优化措施,如何通过改进Group Commit机制显著提升系统的整体性能和稳定性。 ... [详细]
  • 深入浅析JVM垃圾回收机制与收集器概述
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》的阅读心得进行整理,详细探讨了JVM的垃圾回收机制及其各类收集器的特点与应用场景。通过分析不同垃圾收集器的工作原理和性能表现,帮助读者深入了解JVM内存管理的核心技术,为优化Java应用程序提供实用指导。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • 初探性能优化:入门指南与实践技巧
    在编程领域,常有“尚未精通编码便急于优化”的声音。为了从性能优化的角度提升代码质量,本文将带领读者初步探索性能优化的基本概念与实践技巧。即使程序看似运行良好,数据处理效率仍有待提高,通过系统学习性能优化,能够帮助开发者编写更加高效、稳定的代码。文章不仅介绍了性能优化的基础知识,还提供了实用的调优方法和工具,帮助读者在实际项目中应用这些技术。 ... [详细]
  • 尽管我们尽最大努力,任何软件开发过程中都难免会出现缺陷。为了更有效地提升对支持部门的协助与支撑,本文探讨了多种策略和最佳实践,旨在通过改进沟通、增强培训和支持流程来减少这些缺陷的影响,并提高整体服务质量和客户满意度。 ... [详细]
  • 如何在MySQL中选择合适的表空间以优化性能和管理效率
    在MySQL中,合理选择表空间对于提升表的管理和访问性能至关重要。表空间作为MySQL中用于组织和管理数据的一种机制,能够显著影响数据库的运行效率和维护便利性。通过科学地配置和使用表空间,可以优化存储结构,提高查询速度,简化数据管理流程,从而全面提升系统的整体性能。 ... [详细]
  • 美团优选推荐系统架构师 L7/L8:算法与工程深度融合 ... [详细]
  • 本文介绍了UUID(通用唯一标识符)的概念及其在JavaScript中生成Java兼容UUID的代码实现与优化技巧。UUID是一个128位的唯一标识符,广泛应用于分布式系统中以确保唯一性。文章详细探讨了如何利用JavaScript生成符合Java标准的UUID,并提供了多种优化方法,以提高生成效率和兼容性。 ... [详细]
  • Hadoop 2.6 主要由 HDFS 和 YARN 两大部分组成,其中 YARN 包含了运行在 ResourceManager 的 JVM 中的组件以及在 NodeManager 中运行的部分。本文深入探讨了 Hadoop 2.6 日志文件的解析方法,并详细介绍了 MapReduce 日志管理的最佳实践,旨在帮助用户更好地理解和优化日志处理流程,提高系统运维效率。 ... [详细]
  • 在项目开发过程中,掌握一些关键的Linux命令至关重要。例如,使用 `Ctrl+C` 可以立即终止当前正在执行的命令;通过 `ps -ef | grep ias` 可以查看特定服务的进程信息,包括进程ID(PID)和JVM参数(如内存分配和远程连接端口);而 `netstat -apn | more` 则用于显示网络连接状态,帮助开发者监控和调试网络服务。这些命令不仅提高了开发效率,还能有效解决运行时的各种问题。 ... [详细]
author-avatar
业余爱好者
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有