Jvm中GC种类和算法

本文介绍了Java中的垃圾回收(GC)机制,包括GC的基本原理、对象在内存中的状态、引用类型以及垃圾回收算法。重点讲解了各种GC算法如标记-复制、标记-清除和标记-整理,并详细阐述了不同GC收集器的工作方式,如Serial、CMS和G1收集器。文章旨在帮助读者理解Java中GC的工作机制和选择合适的垃圾回收策略。
摘要由CSDN通过智能技术生成

目录

一:什么是GC

二:GC基本原理

1,垃圾回收有哪些特点:

2,在垃圾回收中:对象在内存中的状态

3,对象的强引用,软引用,弱引用和虚引用是什么?

4,如何确定一个对象能被回收?

5,内存分配策略有哪些?

1,概念

2,具体的内存分配策略:

3,触发Full Gc的条件

三: GC的回收算法

1,标记-复制算法

2,标记-清除算法

3,标记-整理算法

4,分代收集 

四:GC的收集器类型

1,Serial收集器(标记-复制算法)

2,Serial Old收集器(标记-整理算法)

3,ParNew收集器(标记-复制)

4,Parallel Scanvenge收集器(标记-复制)

5,Parallel Older收集器(标记-整理)

6,CMS收集器(标记-清楚+标记-整理)

1,初始标记

2,并发标记

3,重新标记 

4,并发清除

7,G1收集器(标记-复制)----未完待续


一:什么是GC

         GC(GarbageCollection)是垃圾回收机制,在Java中开发人员无法使用指针来自由的管理内存,GC是JVM对内存(实际上就是对象)进行管理的方式。GC使得Java开发人员摆脱了繁琐的内存管理工作,让程序的开发更有效率。

二:GC基本原理

        Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的"。GC将负责回收所有"不可达"对象的内存空间。

  对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。但是,为了保证GC能够在不同平台实现的问题,Java规范对GC的很多行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定。因此,不同的JVM的实现者往往有不同的实现算法。这也给Java程序员的开发带来行多不确定性。本文研究了几个与GC工作相关的问题,努力减少这种不确定性给Java程序带来的负面影响。

1,垃圾回收有哪些特点:

垃圾回收有一下特点:

  1. 值回收堆内对象,不回收其他物理资源(eg:数据流连接等)
  2. 无法精确控制内存回收机会,系统会在合适的时机进行内存回收
  3. 在回收对象之前会调用对象的finalize()方法回收资源,这个方法可能会让其他变量重新引用对象导致对象复活。

2,在垃圾回收中:对象在内存中的状态

  1. 可达状态:有一个及以上的变量引用着对象。
  2. 可恢复状态:已经没有变量引用该对象了,但是还没有被调用finalize()方法。系统在回收前会调用finalize()方法,如果在执行finalize方法的时候,重新让一个变量引用了该对象,那该对象会变成可达状态,反之变成不可达状态。
  3. 不可达状态:在执行finalize()方法后,对象还是没有被变量引用则该对象变成不可达状态。

3,对象的强引用,软引用,弱引用和虚引用是什么?

  1. 强引用:就是普通变量对对象的引用,强引用不回被系统回收。如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。比如各种集合的移除方法。
  2. 软引用:软引用是用来描述一些还有用但并非必需的对象。只使用SoftReference类修饰的对象就是一个软引用对象(软可到达对象),如果一个对象只具有软引用,内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
    SoftReference< People > aSoftRef=new SoftReference< People >(obj)
    
    

          常常用于缓存操作,把某个对象标记为软引用时,当内存足够就不会回收,内存不足就会回收,比如网页缓存,图片缓存等。并且软引用都会保证在虚拟机抛出OutOfMemoryError之前已经被清除。

         软引用对象可以和一个引用队列(ReferenceQueue)联合使用。当jvm对软引用对象引用的对象回收后,会将此软引用对象放入关联的队列中。

  3. 弱引用:也是用来描述非必需对象的。只使用WeakReference类修饰的对象就是一个弱引用对象(弱可达对象)。弱引用的对象相比软引用拥有更短暂的生命周期。无论内存是否足够,一旦下次垃圾回收器运行后扫描到弱引用,便会回收。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

    WeakReference< People > reference=new WeakReference< People >(obj);

    如果对象被回收WeakReference的get方法就返回null。引用对象可以和一个引用队列(ReferenceQueue)联合使用。当jvm对弱引用对象引用的对象回收后,会将此弱引用对象放入关联的队列中。

         Java中有WeakHashMap类,以及ThreadLocal中的ThreadLocalMap内部节点Entry,他们都是WeakReference的实现,他们的key都与被弱引用对象关联,key被回收之后就代表这一个无效的Entry,Entry也可以被回收了。

引用测试:

public class ReferenceTest {
    /**
     * 1Mb内存
     */
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws InterruptedException {
        //测试强引用
//        testStrongReference();
        //测试软引用
//        testSoftReference();
        //测试弱引用
//        testWeakReference();
        //测试虚引用
//        testPhantomReference();
    }

    /**
     * 测试强引用
     *
     * @throws InterruptedException
     */
    public static void testStrongReference() throws InterruptedException {
        byte[] StrongReference1, StrongReference2, StrongReference3, StrongReference4;
        StrongReference1 = new byte[1 * _1MB];
        StrongReference2 = new byte[1 * _1MB];
        //到这里由于内存不足,所以虚拟机会自动尝试一次自动GC,但是由于是强引用,无法清除对象,造成OutOfMemoryError异常
        StrongReference3 = new byte[1 * _1MB];
    }

    /**
     * 测试软引用
     *
     * @throws InterruptedException
     */
    public static void testSoftReference() throws InterruptedException {
        ReferenceQueue<byte[]> objectReferenceQueue = new ReferenceQueue<>();
        SoftReference softReference1, softReference2, softReference3, softReference4;
        softReference1 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
        softReference2 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
        //到这里由于内存不足,虚拟机会自动尝试一次自动GC
        softReference3 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
        //执行到这里实际上又GC了一次
        softReference4 = new SoftReference(new byte[1 * _1MB], objectReferenceQueue);
        System.out.println("第一次GC之后的值");
        System.out.println(softReference1.get());
        System.out.println(softReference2.get());
        System.out.println(softReference3.get());
        System.out.println(softReference4.get());
        System.out.println("===========>");
        System.out.println(objectReferenceQueue.poll());
        System.out.println(objectReferenceQueue.poll());
        System.out.println(objectReferenceQueue.poll());
        System.out.println(objectReferenceQueue.poll());
        //到这里,尝试手动使虚拟机GC一次,对于软引用,如果内存足够,GC是并不会回收对象的
        System.gc();
        Thread.sleep(500);
        System.out.println("第二
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值