📜  Java虚拟机-垃圾回收(1)

📅  最后修改于: 2023-12-03 14:43:04.813000             🧑  作者: Mango

Java虚拟机-垃圾回收

在Java中,垃圾回收是一项内存管理机制,目的是在程序运行中自动回收空闲的内存空间,从而防止内存泄漏和内存溢出。Java虚拟机(JVM)垃圾回收机制是自动化的,程序员只需关注程序的逻辑实现,不必担心内存管理问题。

Java中的垃圾回收机制

Java中的垃圾回收机制是基于可达性分析算法实现的。在这个算法中,垃圾回收器会从一组根对象开始对所有可达对象进行扫描,然后扫描对象引用,标记对象为被引用状态。任何未被标记的对象都将被回收。

在Java中,除了基本数据类型,所有其他对象都存储在堆中。当堆中的对象不再被引用时,该对象就称为垃圾。Java虚拟机会自动删除这些垃圾对象,并回收内存空间,从而避免内存泄漏。

垃圾回收算法

Java虚拟机中有多种垃圾回收算法。其中,最常见的是标记-清除算法、复制算法、标记-整理算法和分代收集算法。

标记-清除算法

标记-清除算法是最基本的垃圾回收算法。它通过两个阶段来回收垃圾:标记阶段和清除阶段。在标记阶段,垃圾回收器标记所有从根对象开始可达的对象;在清除阶段,垃圾回收器回收未被标记的对象。由于该算法对内存空间没有规划,因此可能会产生内存碎片,进而影响程序性能。

复制算法

由于标记-清除算法会产生内存碎片,复制算法应运而生。该算法将堆内存分为两个区域:一个是存活区域,一个是空闲区域。在垃圾回收过程中,垃圾回收器将存活对象复制到空闲区域,并清除不需要的对象。该算法不会产生内存碎片,但需要额外的内存空间。

标记-整理算法

标记-整理算法是在标记-清除算法的基础上改进的。与标记-清除算法不同的是,整理算法会在标记阶段标记所有可达对象,并将它们移动到堆的一端。在清除阶段,垃圾回收器将不需要的对象全部清除,并将存活对象移动到另一端。这种算法不会产生内存碎片,但是会在整理过程中移动对象。

分代收集算法

分代收集算法是当前Java虚拟机中最常用的垃圾回收算法。该算法基于两个原则:大部分对象很快就变得不再可用,生命周期长的对象可以存活更长时间。因此,Java虚拟机把堆分成年轻代和老年代,每个部分都用不同的算法进行回收。

年轻代中的对象存活时间很短,因此使用复制算法。年轻代划分为一个Eden区和两个Survivor区。对象首先在Eden区中分配,然后在移动到Survivor区。每次垃圾回收后,从Survivor区迁移到老年代的对象会增加它们的年龄。

老年代中的对象存活时间更长,因此使用标记-清除算法和标记-整理算法。老年代中的垃圾回收会频率很低,因此会影响程序性能。为了优化该算法,Java虚拟机使用记忆回收(card table),即只回收改变的部分,而不去检查整个老年代中的对象。

垃圾回收器

Java虚拟机中有多个垃圾回收器。每个垃圾回收器都有自己的内存管理机制和效率。在选择垃圾回收器时,应该根据程序的需求、硬件环境、内存大小等因素来考虑。以下是几个常见的垃圾回收器:

Serial收集器

Serial收集器是最古老的垃圾回收器之一。它是单线程的,只适合运行在小型的JVM和单CPU的环境中。

Parallel收集器

Parallel收集器是多线程垃圾回收器,适用于多CPU的环境中。它会使用多线程来加速垃圾回收,但是会占用更多的CPU资源。

CMS收集器

CMS收集器是一种基于标记-清除算法的垃圾回收器。该算法不会暂停整个Java虚拟机,因此不会影响程序的性能。但是由于它不会对内存空间进行整理,因此会产生内存碎片。

G1收集器

G1收集器是一种基于分代收集算法的垃圾回收器。它将堆内存分为多个区域,并使用复制算法和标记整理算法来回收垃圾。G1优化了内存分配和回收的速度,并有效减少了内存碎片的产生。它也是Java 9的默认垃圾回收器。

总结

在Java中,垃圾回收机制使程序员不必担心内存管理问题,从而可以更加专注于程序的逻辑实现。Java虚拟机中的垃圾回收器和垃圾回收算法具有多样性,程序员可以根据程序的需求和硬件环境来选择最适合的垃圾回收器。