JVM垃圾回收

JVM垃圾回收

一、如何判断对象可以回收

1、引用计数法

使用引用计数的方式判断对象是否需要回收

**缺点:**当两个对象循环引用时会导致引用计数法失效

在这里插入图片描述

jvm没有使用此方法

2、可达性分析算法

确定根对象(不可以被回收的对象),对堆中的所有对象进行扫描,判断对象是否被根对象直接或间接引用,被引用则不可以被回收。

2.1使用ecplise工具Memory Analyzer
2.2示例代码
List<Object> listos = new ArrayList<>();
listos.add("a");
listos.add("b");
System.out.println("1");
System.in.read();

listos = null;
System.out.println("2");
System.in.read();
System.out.println("end..........");
2.3生成堆转储文件
  • 查看java进程
jps
  • 使用以下命令进行堆转储
jmap -dump:format=b,live,file=要储存的文件名 进程id
2.4使用Memory Analyzer
  • 使用File->Open File打开堆转储文件
  • 打开Java Basics->GC Roots

在这里插入图片描述

2.5结果图示
  • 引用ArrayList对象时

在这里插入图片描述

  • 将对象置空,垃圾回收后

在这里插入图片描述

3、引用方式

在这里插入图片描述

3.1强引用

当对象没有任何根对象(GC Roots)强引用时就可以被回收

3.2软引用(SoftReference)

当对象只有软引用对象引用时,并且发生一次垃圾回收并且内存依旧不足的情况下再次进行垃圾回收,此时会回收该对象

当软引用对象引用的对象被垃圾回收后,软引用对象会进入引用队列,以便进行内存回收

3.3弱引用(WeakReference)

当对象仅有弱引用对象引用时,在垃圾回收时会直接回收该对象,无论内存是否充足

当弱引用对象引用的对象被垃圾回收后,弱引用对象会进入引用队列,以便进行内存回收

3.4虚引用(PhantomReference)

此引用方式必须配合引用队列使用

在创建ByteBuffer时会有一个虚引用对象Cleaner引用ByteBuffer,在没有根对象引用这个ByteBuffer对象时,ByteBuffer就可以被垃圾回收。但是在ByteBuffer对象被垃圾回收后,它使用的直接内存是没有被释放的,此时虚引用对象Cleaner就会进入引用队列。此时后台进程ReferenceHandler会检查引用队列,并执行Cleaner对象中的clean方法在其中调用Unsafe.freeMemory方法对直接内存进行释放操作

3.5终结器引用(FinalReference)

在重写finallize方法的对象没有根对象强引用它时,在垃圾回收时,jvm会创建一个终结器引用对象,并将此终结器对象放入引用队列。此时会由后台线程FinalizerThread会使用终结器对象引用调用对象中的finallize方法,此时,对象就可以被垃圾回收。

3.6示例(软引用)
        List<SoftReference<byte[]>> list = new ArrayList<>();
        
        //创建引用队列
        ReferenceQueue<byte[]> referenceQueue = new ReferenceQueue<>();
        for (int i = 0; i < 5; i++) {
            //将引用队列与软引用关联
            SoftReference<byte[]> softReference = new SoftReference<>(new byte[_4M], referenceQueue);
            System.out.println(softReference.get());
            list.add(softReference);
            System.out.println(list.size());
        }

        //将引用队列中最先进入队列的软引用对象取出,并从list中移除
        Reference<? extends byte[]> poll = referenceQueue.poll();
        while (poll != null){
            list.remove(poll);
            poll = referenceQueue.poll();
        }

        System.out.println("over---------------");
        for (SoftReference<byte[]> sr : list){
            System.out.println(sr.get());
        }

        /**
         * 输出:
         * [B@1d81eb93
         * [B@7291c18f
         */

二、垃圾回收算法

1、标记清除

定义:Mark Sweep

  • 图示

在这里插入图片描述

  • 会导致存入较大的对象时因为碎片化程度较高,有可能导致内存溢出

2、标记整理

定义:Mark Compact

  • 图示

在这里插入图片描述

  • 标记整理时需要移动内存中对象的位置,所以对性能耗费较大

3、复制

定义:Copy

  • 图示

在这里插入图片描述

  • 由于此方式会将内存分为两个区,因此会占用双份的内存空间

三、分代垃圾回收

在这里插入图片描述

在对象新创建时会加入伊甸园,当伊甸园的空间不足之后会触发一次Minor GC ,将伊甸园和from存活的对象使用Copy复制到幸存区To中,将存活的对象年龄加1并交换From和To。在触发Minor GC时会引发Stop the world,暂停其他用户的线程,等垃圾回收结束,用户线程才恢复运行。在对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4 bit)。当老年代空间不足,会尝试触发Minor GC,如果之后空间仍然不足,会触发Full GC,STW的时间更长。

1、相关VM参数

含义参数
堆初始大小-Xms
堆最大大小-Xms-XX:MaxHeapSize=size
新生代大小-Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size)
幸存区比例(动态)-XX:InitialSurvivorRatio=ratio-XX:+UseAdaptiveSizePolicy
幸存区比例-XX:SurvivorRatio=ratio
晋升阈值-XX:MaxTenuringThreshold=threshold
晋升详情-XX:+PrintTenuringDistribution
GC详情-XX:+PrintGCDetails -verbose:gc
Full GC 前 Minor GC-XX:+ScavengeBeforeFullGC

四、垃圾回收器

1、串行

  • 单线程
  • 堆内存较小,适合个人电脑

-XX:+UseSerialGC = Serial + SerialOld

在这里插入图片描述

2、吞吐量优先

  • 多线程
  • 堆内存较大,多核CPU
  • 让单位时间内,STW的时间最短 0.2 0.2 = 0.4

-XX:+UseParallelGC ~ -XX:+UseParallelOldGC

-XX:+UseAdaptiveSizePolicy:新生代自适应大小调整策略

-XX:GCTimeRatio=ratio:默认值:99,公式:1/(1+ratio)会根据此公式动态调整堆大小

-XX:MaxGCPauseMillis=ms:默认值200msGC最大用时,会根据此值动态调整堆大小

-XX:ParallelGCThreads=n:控制线程数

在这里插入图片描述

3、响应时间优先

  • 多线程
  • 堆内存较大,多核CPU
  • 尽可能让单次STW的时间最短 0.1 0.1 0.1 0.1 0.1 = 0.5

-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld

-XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads:参数一:并行垃圾回收线程数,默认为CPU核数。参数二:并发垃圾回收线程数,一般为并行垃圾回收线程数的四分之一。

-XX:CMSInitiatingOccupancyFraction=Percent:当内存占用达到多少百分比时执行垃圾回收

-XX:+CMSScavengeBeforeRemark:在重新标记之前先进行一次新生代垃圾回收

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌尘吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值