jvm垃圾回收机制

    JVM 垃圾回收机制是Java语言的一个重要特性,它负责自动管理程序运行时产生的内存,以便释放不再使用的对象,防止内存泄漏并提高程序性能。以下是Java的JVM垃圾回收机制的主要概念:

  1. 堆内存(Heap Memory): JVM的堆内存是用于存储对象实例的区域。所有通过new关键字创建的对象都被分配到堆内存中。

  2. 垃圾对象(Garbage Objects): 当对象不再被引用时,它就成为垃圾对象。没有任何引用指向一个对象时,它就变得可回收。

  3. 引用计数算法: 一种简单的垃圾回收算法是引用计数。每个对象都有一个引用计数,当有新的引用指向对象时,计数加一,当引用失效时,计数减一。当计数为零时,对象被认为是垃圾并被回收。然而,Java不使用引用计数算法,因为它无法解决循环引用的问题。

  4. 可达性分析算法: Java使用的是可达性分析算法,通过一组称为"GC Roots"的对象作为起始点,从这些点开始向下搜索,能够到达的对象被认为是可达的,而无法到达的对象则被判定为垃圾。常见的GC Roots包括虚拟机栈中的本地变量表、方法区中类静态属性引用的对象等。

  5. 标记-清除算法: 这是可达性分析算法的一种实现方式。首先,标记阶段遍历所有可达的对象并进行标记,然后在清除阶段,未被标记的对象被当做垃圾进行回收。

  6. 复制算法: 为了提高清除阶段的效率,一些垃圾回收器采用复制算法。堆内存被划分为两个区域,每次只使用其中一个。当一个区域的空间用尽时,将其中存活的对象复制到另一个区域,然后清空原区域的内容。这样可以减少碎片,但也需要额外的空间。

  7. 标记-整理算法: 这是标记-清除算法的改进版,它在标记阶段标记存活对象,然后将它们移动到内存的一端,最后清理掉边界外的对象,从而减少内存碎片。

  8. 分代回收: 根据对象的生命周期,堆内存一般被划分为新生代和老年代。新创建的对象首先被分配到新生代,而存活时间较长的对象则会被移到老年代。不同的回收算法和机制可以根据每个代的特性进行优化。

垃圾回收算法:

  1. 标记-清除算法(Mark-and-Sweep):

    • 标记阶段: 从GC Roots出发,标记所有可达对象。
    • 清除阶段: 清除未被标记的对象,释放空间。

    示例:

     

    javaCopy code

    // 创建一个循环引用的对象 class Node { Node next; } Node objA = new Node(); Node objB = new Node(); objA.next = objB; objB.next = objA; // 在这里,objA和objB形成了一个循环引用 // 当没有任何引用指向objA和objB时,标记-清除算法可以回收这两个对象。 objA = null; objB = null;

  2. 复制算法(Copying):

    • 将堆内存划分为两个区域,每次只使用其中一个,当一个区域的空间用尽时,将存活的对象复制到另一个区域。

    示例:

     

    javaCopy code

    // 创建一个大对象 byte[] largeObject = new byte[10 * 1024 * 1024]; // 大对象存活后,复制算法会将其复制到另一个区域,然后清空原区域

  3. 标记-整理算法(Mark-and-Compact):

    • 标记存活对象,将它们移动到内存一端,然后清理边界外的对象,减少内存碎片。

    示例:

     

    javaCopy code

    // 创建一些对象并使其中一些成为垃圾 Object obj1 = new Object(); Object obj2 = new Object(); Object obj3 = new Object(); obj1 = null; // obj1成为垃圾 // 标记-整理算法会将存活对象obj2和obj3移动到内存一端

分代回收:

JVM将堆内存划分为不同的代,主要分为新生代(Young Generation)和老年代(Old Generation)。

  1. 新生代(Young Generation):

    • 大多数对象在创建后很快就不再使用,因此新生代采用复制算法,将对象分为Eden区和两个Survivor区,通过不断将存活的对象从Eden区复制到Survivor区,最终存活的对象进入老年代。

    示例:

     

    javaCopy code

    // 创建对象并分配到新生代的Eden区 Object obj1 = new Object(); Object obj2 = new Object(); // obj1成为垃圾,obj2被移到Survivor区 // 经过多次垃圾回收后,存活的对象可能会被移到老年代

  2. 老年代(Old Generation):

    • 存活时间较长的对象被移到老年代。老年代一般采用标记-整理算法或标记-清除-整理算法。

    示例:

     

    javaCopy code

    // 创建对象并使其成为垃圾 Object obj3 = new Object(); // obj3可能会被移到老年代

引用类型:

Java中有不同的引用类型,这些类型影响垃圾回收的行为,包括强引用、软引用、弱引用和虚引用。

 
  

javaCopy code

// 强引用 Object obj = new Object(); // 软引用 SoftReference softRef = new SoftReference<>(obj); // 弱引用 WeakReference weakRef = new WeakReference<>(obj); // 虚引用 ReferenceQueue referenceQueue = new ReferenceQueue<>(); PhantomReference phantomRef = new PhantomReference<>(obj, referenceQueue);

不同引用类型在对象变为垃圾时的处理方式不同,这有助于开发者更灵活地管理内存。

你可能感兴趣的:(jvm)