垃圾回收的核心知识点解析

简介: 垃圾回收的核心知识点解析

Java运行时内存中的程序计数器、虚拟机栈、本地方法栈这三部分区域其生命周期与相关线程有关,随线程而生,随线程而灭。而程序计数器就是一个单纯存地址的整数也不需要关心,因此我们GC(垃圾回收)的主要目标就是堆(堆中存放着几乎所有实例对象)!

检测垃圾

一个对象,如果后续不再被使用且没有引用指向它,就可以认为是垃圾。

有以下方法可知对象是否有引用指向:

引用计数算法

在主流的JVM中没有选用引用计数法来管理内存,最主要的原因就是引用计数法无法解决对象的循环引用问题 Python,PHP采取了引用计数算法。

给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即可被回收。

Test test1 = new Test();
        Test test2 = test1;
        Test test3 = test1;
        Test test4 = test1;

此算法存在两个缺陷:

  1. 浪费内存空间
  2. 存在循环引用的情况
    用一个例子来解释一下循环引用的问题:
class Test {
 public Test test;
}
        Test test1 = new Test();
        Test test2 = new Test();
        test1.test=test2;
        test2.test=test1;

此时test1与test2 销毁了,两个对象的引用计数分别减一。

此时这两个对象的引用计数不为0,不能作为垃圾且无法使用,陷入了一个逻辑上的循环。

可达性分析算法

通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称之为"引用链",当一个对象到GC Roots没有任何的引用链相连时(从GC Roots到这个对象不可达)时,证明此对象是不可用的

在java中,可作为GC Roots(垃圾回收根对象)的对象有以下几种:

  1. 栈上的局部变量
  2. 常量池中引用的对象
  3. 方法区中类静态属性引用的对象

只有从GC Roots对象开始,通过引用链可达的对象才被认为是存活的,而无法通过引用链访问的对象则会被判定为垃圾,并进行回收。

缺点:

  1. 遍历开销:可达性分析算法需要遍历整个对象图以确定每个对象的可达性。对于大型堆和复杂的引用关系,遍历开销可能非常大,特别是在全局垃圾回收中。这可能会导致垃圾回收的性能下降。
  2. 延迟回收:可达性分析算法需要遍历整个对象图,从GC Roots开始,逐个检查每个对象的引用关系。这个过程可能需要消耗大量的时间,且在垃圾回收期间,应用程序的执行会被暂停(STW - Stop-The-World)。因此,可达性分析算法可能导致较高的延迟,影响程序的响应性能。

回收垃圾

标记清除算法

算法分为"标记"和"清除"两个阶段 : 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

回收前:

回收后:

不足:

  1. 标记和清除这两个过程的效率都不高。
  2. 标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行中需要分配较大对象时,无法找到足够连续内存而不得不提前触发另一次垃圾收集。

复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。

简单来说复制算法就是把不是垃圾的对象拷贝到未使用的那一边,然后再统一释放刚才使用过的那一块区域

缺点:

  1. 内存利用率比较低。
  2. 如果当前区域的大部分对象都需要保留垃圾很少,那么此时的复制成本就比较高。

标记整理算法

标记整理算法的基本流程:

  1. 标记:从根对象开始,通过可达性分析算法,标记所有从根对象可达的存活对象。标记过程中,通常使用标记位(标记状态)来标记对象是否为存活对象。
  2. 整理:将所有存活对象移到堆的一端,紧凑排列,以便释放出连续的一段内存空间。在移动存活对象时,需要更新对这些对象的引用,确保引用指向移动后的新位置。
  3. 更新引用:在堆中,遍历所有存活对象的引用,将其指向新的位置。这是为了避免悬挂指针(引用指向被移动或已回收的对象)的问题。
  4. 释放未标记的对象:在整理后的堆中,所有没有被标记的对象都可以被认为是垃圾对象,可以直接被回收。

优点:解决了内存碎片问题。

缺点:搬运复制开销比较大。

分代算法

分代算法主要基于一种观察:大部分对象的生命周期都比较短暂。根据这个观察,分代算法将堆内存划分为不同的代(Generation),每一代中对象的生命周期不同,并且根据对象的生命周期将不同的垃圾回收策略应用于不同的代中。

一般来说,分代堆内存被划分为年轻代(Young Generation)和老年代(Old Generation)两个主要部分

年轻代

年轻代是存放新创建的对象的地方,大部分对象在创建后很快就变为垃圾对象。年轻代通常进一步分为Eden区和两个Survivor区。新创建的对象首先放入Eden区,当Eden区满时,不会被回收的对象会被转移到一个Survivor区。当一个Survivor区满时,其中的存活对象会被复制到另一个Survivor区或者老年代。经过多次垃圾回收后依然存活的对象将晋升到老年代。

年轻代通常采用复制算法(Copying)作为垃圾回收策略,因为新创建的对象的生命周期短暂,复制算法可以更好地利用对象的特点。

老年代

老年代是存放存活时间较长的对象的地方,老年代的对象生命周期较长,垃圾回收频率相对较低。对于老年代的垃圾回收,可以采用标记-清除(Mark-Sweep)或者标记-整理(Mark-Compact)等算法。

分代算法通过区分不同代的对象,针对不同代采取不同的垃圾回收策略,可以提高垃圾回收效率和系统性能。年轻代的频繁垃圾回收可以快速回收新创建对象,老年代的较少回收可以减少全局垃圾回收的引发,提高应用程序的响应性。这种分代垃圾回收策略在大多数的垃圾收集器中都有应用。


相关文章
|
21天前
|
SQL 分布式计算 监控
Sqoop数据迁移工具使用与优化技巧:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入解析Sqoop的使用、优化及面试策略。内容涵盖Sqoop基础,包括安装配置、命令行操作、与Hadoop生态集成和连接器配置。讨论数据迁移优化技巧,如数据切分、压缩编码、转换过滤及性能监控。此外,还涉及面试中对Sqoop与其他ETL工具的对比、实际项目挑战及未来发展趋势的讨论。通过代码示例展示了从MySQL到HDFS的数据迁移。本文旨在帮助读者在面试中展现Sqoop技术实力。
91 2
|
21天前
|
监控 负载均衡 Cloud Native
ZooKeeper分布式协调服务详解:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入剖析ZooKeeper分布式协调服务原理,涵盖核心概念如Server、Client、ZNode、ACL、Watcher,以及ZAB协议在一致性、会话管理、Leader选举中的作用。讨论ZooKeeper数据模型、操作、会话管理、集群部署与管理、性能调优和监控。同时,文章探讨了ZooKeeper在分布式锁、队列、服务注册与发现等场景的应用,并在面试方面分析了与其它服务的区别、实战挑战及解决方案。附带Java客户端实现分布式锁的代码示例,助力提升面试表现。
411 2
|
21天前
|
数据采集 消息中间件 监控
Flume数据采集系统设计与配置实战:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入探讨Apache Flume的数据采集系统设计,涵盖Flume Agent、Source、Channel、Sink的核心概念及其配置实战。通过实例展示了文件日志收集、网络数据接收、命令行实时数据捕获等场景。此外,还讨论了Flume与同类工具的对比、实际项目挑战及解决方案,以及未来发展趋势。提供配置示例帮助理解Flume在数据集成、日志收集中的应用,为面试准备提供扎实的理论与实践支持。
49 1
|
18天前
|
存储 Java 程序员
【Python 的内存管理机制专栏】深入解析 Python 的内存管理机制:从变量到垃圾回收
【5月更文挑战第18天】Python内存管理关乎程序性能与稳定性,包括变量存储和垃圾回收。变量存储时,如`x = 10`,`x`指向内存中值的引用。垃圾回收通过引用计数自动回收无引用对象,防止内存泄漏。了解此机制可优化内存使用,避免循环引用等问题,提升程序效率和稳定性。深入学习内存管理对成为优秀Python程序员至关重要。
【Python 的内存管理机制专栏】深入解析 Python 的内存管理机制:从变量到垃圾回收
|
21天前
|
机器学习/深度学习 分布式计算 BI
Flink实时流处理框架原理与应用:面试经验与必备知识点解析
【4月更文挑战第9天】本文详尽探讨了Flink实时流处理框架的原理,包括运行时架构、数据流模型、状态管理和容错机制、资源调度与优化以及与外部系统的集成。此外,还介绍了Flink在实时数据管道、分析、数仓与BI、机器学习等领域的应用实践。同时,文章提供了面试经验与常见问题解析,如Flink与其他系统的对比、实际项目挑战及解决方案,并展望了Flink的未来发展趋势。附带Java DataStream API代码样例,为学习和面试准备提供了实用素材。
99 0
|
21天前
|
分布式计算 资源调度 监控
Hadoop生态系统深度剖析:面试经验与必备知识点解析
本文深入探讨了Hadoop生态系统的面试重点,涵盖Hadoop架构、HDFS、YARN和MapReduce。了解Hadoop的主从架构、HDFS的读写流程及高级特性,YARN的资源管理与调度,以及MapReduce编程模型。通过代码示例,如HDFS文件操作和WordCount程序,帮助读者巩固理解。此外,文章强调在面试中应结合个人经验、行业动态和技术进展展示技术实力。
|
21天前
|
存储 缓存 算法
深度解析JVM世界:垃圾判断和垃圾回收算法
深度解析JVM世界:垃圾判断和垃圾回收算法
|
21天前
|
网络协议
有关DNS64的知识点
总之,DNS64在IPv6-only环境中扮演着重要的角色,通过地址转换使得IPv6设备能够访问IPv4资源,促进了IPv6的部署和演进。
138 0
|
21天前
|
存储 安全 API
掌握 HTTP Authorization 头:关键知识点解析
在当今的互联网世界中,安全性贯穿于 web 应用的每个方面,HTTP Authorization 头的使用在这个过程中扮演着不可或缺的角色。它是 HTTP 请求中的一个重要部分,用来在客户端和服务器之间安全地传输认证信息。用途广泛,无论是浏览器还是其他客户端应用,都依赖它来验证用户的访问权限。本文旨在详细解读 HTTP Authorization 头的定义、使用方式以及不同的认证机制。
|
21天前
|
监控 Java 开发者
JDK 9新特性深度解析:垃圾回收器的改进与优化
本文将深入探讨JDK 9中垃圾回收器的改进与优化。随着Java语言的不断发展,垃圾回收器作为内存管理的核心组件也经历了多次迭代和改进。JDK 9引入了新的垃圾回收器,旨在提高内存回收的效率和性能,降低垃圾回收的停顿时间。本文将详细介绍这些改进,以及如何在实际应用中利用这些改进来提高应用程序的性能和稳定性。

推荐镜像

更多