垃圾回收与内存管理
一、什么是垃圾回收
标题为 一、什么是垃圾回收垃圾回收是内存管理的工具,用于回收已失去所有引用的对象占用的内存空间。这些对象被称为“垃圾”
要理解垃圾回收,需要理解以下几个问题::
- 哪些内存需要回收?
- 什么时候回收?
- 如何回收?
二、哪些内存需要回收
标题为 二、哪些内存需要回收垃圾回收的目标是清除不再使用的内存,但判断何时回收对象却很困难。
2.1、引用计数法
标题为 2.1、引用计数法引用计数法是一种简单的判断对象是否可回收的方法。每个对象维护一个引用计数器,当对象被其他对象引用时,计数器加1;当对象的引用被删除时,计数器减1。当计数器值为0时,该对象可以被回收。
然而,引用计数法存在缺陷,无法处理循环引用的情况,导致对象无法正确回收。
2.2、可达性分析算法
标题为 2.2、可达性分析算法为了解决循环引用的问题,又引出了一个新的算法
可达性算法的原理是以一系列叫做 GC Root
的对象为起点出发,引出它们指向的下一个节点,再以下个节点为起点,引出此节点指向的下一个结点。这样通过 GC Root 串成的一条线就叫引用链),直到所有的结点都被访问完毕。如果一个对象没有任何引用链相连,即 GC Root 到这个对象不可达,则证明此对象不可用,可以被回收
现代虚拟机基本都是采用可达性分析算法
2.2.1、GC Roots
标题为 2.2.1、GC RootsGC Roots的对象包括以下几种:
- 在虚拟机栈中引用的对象,如方法中的参数、局部变量等
- 在方法区中类静态属性引用的对象
- 在方法区中常量引用的对象
- 在本地方法栈中JNI(Native方法)引用的对象
- Java虚拟机内部的引用,如Class对象、系统类加载器等
- 所有被同步锁(synchronized关键字)持有的对象
- 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等
2.2.2、对象自救
标题为 2.2.2、对象自救Java提供了finalize
方法,垃圾回收器在回收对象之前会调用该方法。如果在finalize
方法中,对象又重新连接了GC Roots,那么该对象将存活下来。
然而,从Java 9开始,finalize
方法已被标记为@Deprecated
,不再推荐使用。
2.3、方法区的回收
标题为 2.3、方法区的回收方法区并不在堆里,但是它也是可以被回收的。方法区的垃圾收集主要回收两部分内容:
- 废弃的常量
- 不再使用的类型
一个类型被判定为“不再使用”的条件包括:
- 该类所有的实例都已被回收,即Java堆中不存在该类及其任何派生子类的实例。
- 加载该类的类加载器已被回收。
- 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
若满足这三个条件,虚拟机可以对该类型进行回收。
三、垃圾回收算法
标题为 三、垃圾回收算法3.1、分代收集
标题为 3.1、分代收集常用的垃圾收集器都遵循着一个共同的设计原则,即将Java堆划分为不同的区域,然后将回收对象依据其年龄分配到不同的区域之中存储,这就是分代收集的理论。
分代收集主要划分为新生代和老年代,不同区域应用不同的回收策略,使得垃圾回收更高效。
3.2、回收算法
标题为 3.2、回收算法
我们需要了解的垃圾回收算法有以下几种:
- 标记-清除算法
- 标记-复制算法
- 标记-整理算法
这些算法的优缺点都是非常明显的
3.2.1、标记-清除算法
标题为 3.2.1、标记-清除算法该算法最早出现也最基础,正如名字一样,分为两个步骤:标记和清除,标记可以是标记保留的对象也可以是标记可回收的对象
它主要存在两个问题
- 效率不稳定 - 堆中有大量对象,且大多是要回收的情况下,需要频繁执行标记-清除动作
- 会产生大量内存碎片
3.2.2、标记-复制算法
标题为 3.2.2、标记-复制算法该算法为了解决·标记-清除算法效率不稳定的问题引入,它的思想是将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉
这个算法解决了效率不稳定的问题,也不会产生内存碎片,但是它引出了新的问题:
- 存活对象多的情况下,内存复制的开销很大
- 可用内存缩水到原来的一半
也因此,该算法主要用在新生代存活对象较少的情况下
3.2.3、标记-整理算法
标题为 3.2.3、标记-整理算法复制算法的特性决定了它不能用在老年代中,针对老年代的特性引入了该方法,标记的阶段和标记-清除算法一样,不同的是,可回收对象并不会直接清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存
四、QA概要
标题为 四、QA概要-
什么是垃圾回收?
- 垃圾回收是内存管理的工具,用于回收已失去所有引用的对象占用的内存空间,这些对象被称为”垃圾”。垃圾回收通过自动处理内存释放,帮助程序员更轻松地管理内存。
-
垃圾回收的过程和原理是怎样的?
- 垃圾回收主要通过判断对象是否可达来确定哪些内存需要回收。最常用的方法是可达性分析算法,以一系列称为”GC Root”的对象为起点,沿着引用链找出所有可达的对象,未被访问到的对象则被认为是垃圾并可以被回收。
- 引用计数法是另一种简单的回收方法,但因为无法处理循环引用导致的问题,现代虚拟机一般采用可达性分析算法。
- 方法区也可以进行垃圾回收,主要回收废弃的常量和不再使用的类型。
-
垃圾回收算法有哪些?
- 常见的垃圾回收算法包括标记-清除算法、标记-复制算法和标记-整理算法。
- 标记-清除算法最早且最基础,分为标记和清除两个步骤,但效率不稳定且会产生大量内存碎片。
- 标记-复制算法为了解决标记-清除算法的问题而引入,将可用内存划分为两块,每次只使用其中一块,回收时将存活的对象复制到另一块上。
- 标记-整理算法主要用于老年代,标记的阶段与标记-清除算法相同,不同的是可回收对象不会直接清理,而是让存活的对象向内存一端移动后清理边界以外的内存。