JVM性能优化(二)垃圾回收算法详解(1)

简介: JVM性能优化(二)垃圾回收算法详解

文章目录


一、什么是垃圾回收

1.1 C/C++语言的垃圾回收

1.2 Java语言的垃圾回收

二、垃圾回收的常见算法

2.1 引用计数法

2.1.1 原理

2.1.2 优缺点

2.2 标记清除法

2.2.1 原理:

2.2.2 优缺点:

2.3 标记压缩算法

2.3.1 原理:

2.3.2 优缺点:

2.4 复制算法

2.4.1 JVM中年轻代内存空间:

2.4.2 优缺点

2.4 分代算法

三、垃圾收集器以及内存分配

3.1、串行垃圾收集器

3.1.1 编写测试代码

3.1.2 设置垃圾回收为串行收集器

3.2、并行垃圾收集器

3.2.1 parNew垃圾收集器

3.2.2 ParallelGC垃圾收集器

3.3、CMS垃圾收集器

四、结束语



一、什么是垃圾回收


程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占用内存资源,最终将导致内存溢出,所以对内存资源的管理是非常重要了。


1.1 C/C++语言的垃圾回收


在C/C++语言中,没有自动垃圾回收机制,是通过new关键字申请内存资源,通过delete 关键字释放内存资源,如果程序员在某些位置没有写delete进行释放,那么申请的对象将一直占用内存资源,最终可能会导致内存溢出。


1.2 Java语言的垃圾回收


为了让程序员更专注于代码的实现,而不用过多的考虑内存释放的问题,所以在Java语言中,有了自动的垃圾回收机制,也就是我们熟悉的GC。

有了垃圾回收机制后,程序员只需要关心内存的申请即可,内存的释放由系统自动识别完成。

换句话说,自动的垃圾回收的算法会变得非常重要了,如果因为算法的不合理,导致内存一直没有释放,同样也可能会导致内存溢出的。

除了Java语言,C#、Python等语言也都有自动的垃圾回收机制。


二、垃圾回收的常见算法


自动化的管理内存资源,垃圾回收机制必须要有一套算法来进行计算,哪些是有效的对象,哪些是无效的对象,对于无效的对象就要进行回收处理。

常见的垃圾回收算法有:引用计数法、标记清除法、标记压缩法、复制算法、分代算法等。


2.1 引用计数法


引用计数是历史最悠久的一种算法,最早George E.Collins在1960的时候首次提出,50年后的今天,该算法依然被很多编程语言使用。


2.1.1 原理


假设有一个对象A,任何一个对象对A的引用,那么对象A的引用计数器+1,当引用失败时,对象A的引用计数器就-1,如果对象A的计数器的值为0,就说明对象A没有引用了,可以被回收。


如图所示:

image.png


2.1.2 优缺点


优点:


实时性较高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否为0,就可以直接回收。

在垃圾回收过程中,应用无需挂起,如果申请内存时,内存不足,则立刻报 outofmember 错误。

区域性,更新对象的计数器时,只是影响到该对象,不会扫描全部对象。

缺点:


每次对象被引用时,都需要去更新计数器,有一点时间开销。

浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。

无法解决循环引用问题。(最大缺点)

什么是循环引用:

class TestA{
  public TestB b;
}
class TestB{
  public TestA a;
}
public class TestCycle {
  public static void main(String[] args) {
    TestA a = new TestA();
    TestB b = new TestB();
    a.b = b;
    b.a = a;
    a = null;
    b = null;
  }
}

屏幕快照 2022-05-10 下午3.17.59.png


2.2 标记清除法

标记清除算法,是将垃圾回收分为2个阶段,分别是 标记和清除

  • 标记:从根节点开始标记引用的对象
  • 清除:未被标记引用的对象就是垃圾对象,可以被清理

屏幕快照 2022-05-10 下午3.18.42.png

2.2.2 优缺点:


可以看到,标记清楚算法解决了引用计数算法中的循环引用的问题,没有从root节点引用的对象都会被回收。

同样标记清楚算法也是有缺点的:


效率较低,标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常差的。

通过标记清楚算法清理出来的内存,碎片化较为严重,因为被回收的对象可能存在于内存的各个角落,所以清理出来的内存时不连贯的。

2.3 标记压缩算法


标记压缩算法是在标记清除算法的基础之上,做了优化改进的算法,和标记清除算法一样,也是从根节点开始,对对象的引用进行标记,在清理阶段,并不是简单的清理未标记的对象,而是将存活的对象压缩到内存的一端,然后清理边界以外的垃圾,从而解决了碎片化的问题。


2.3.1 原理:

image.png

2.3.2 优缺点:

优缺点同标记算法,解决了标记清除算法的碎片化的问题,同时,标记压缩算法多了一步,对象移动内存位置的步骤,其效率也是有一定的影响。


目录
相关文章
|
2月前
|
存储 算法 Java
jvm性能优化(一)-基于JDK1.8
jvm性能优化(一)-基于JDK1.8
|
24天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
48 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
22天前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
8天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
12 3
|
13天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
25天前
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
26天前
|
算法 Java
谈谈HotSpot JVM 中的不同垃圾回收器
【10月更文挑战第5天】理解 HotSpot JVM 中的不同垃圾回收器(如 CMS、G1 和 ZGC)的区别,需要深入了解它们的设计原理、工作方式和应用场景。以下是对这三个垃圾回收器的简要概述以及一个示例 Java 程序,虽然示例程序本身不能直接展示垃圾回收器的内部机制,但可以帮助观察不同垃圾回收器的行为。
15 1
|
1月前
|
存储 算法 Java
【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收
【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收
45 2
|
20天前
|
算法 JavaScript 前端开发
垃圾回收算法的原理
【10月更文挑战第13天】垃圾回收算法的原理
21 0
|
2月前
|
存储 算法 Java
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制
本文介绍了 JVM 的内存区域划分、类加载过程及垃圾回收机制。内存区域包括程序计数器、堆、栈和元数据区,每个区域存储不同类型的数据。类加载过程涉及加载、验证、准备、解析和初始化五个步骤。垃圾回收机制主要在堆内存进行,通过可达性分析识别垃圾对象,并采用标记-清除、复制和标记-整理等算法进行回收。此外,还介绍了 CMS 和 G1 等垃圾回收器的特点。
104 0
深入解析 Java 虚拟机:内存区域、类加载与垃圾回收机制