• JVM阶段(4)-回收策略


    1.概述

    回忆一下,运行时数据区哪些部分会产生OOM异常,如果无休止的创建对象,或者类信息,或者往运行时常量池塞数据,都可能导致OOM。为了避免这种情况,就需要去考虑底层的垃圾收集。

    那么,哪些内存需要回收。

    什么时候来回收。

    如何回收。

    这三个问题,其实就是垃圾回收器的本质。当然,先从哪些内存需要回收说起。

    其实主要就是堆和方法区,其它的都是线程私有,线程挂,直接无。

    2.回收策略

    关于回收策略,其实大多说的都是堆这一块,哪些对象需要回收。这就用到了引用计数法,以及可达性分析算法。

    2.1 引用计数法

    引用计数法,首先声明,这个算法Java之中是不用的。可以想想,底层支撑的数据结构,双向链表,注定了两个对象肯定是持有各自的引用的,要用这种算法无法回收。

    引用计数法,可以理解为每个对象都有一个引用数,reference counting,当这个数为0时,代表了任何对象都没有引用该对象,它没用了,所以回收。

    反向证明下,java内部使用的不是引用计数法。

    1. package com.bo.jvmstudy.thirdchapter;
    2. /**
    3. * @Auther: zeroB
    4. * @Date: 2022/8/31 20:46
    5. * @Description: 证明GC不是引用计数法
    6. * -Xmx20m -Xms20m -XX:+PrintGCDetails
    7. */
    8. public class ReferenceCountingTest {
    9. //内部类设置个1M空间,明显点
    10. static class Obj{
    11. private Integer[] arr = new Integer[1024*1024];
    12. public Obj obj;
    13. }
    14. public static void main(String[] args) {
    15. Obj obj1 = new Obj();
    16. Obj obj2 = new Obj();
    17. obj1.obj = obj2;
    18. obj2.obj = obj1;
    19. obj1 = null;
    20. obj2 = null;
    21. /*
    22. ,[GC (System.gc()) [PSYoungGen: 2170K->504K(6144K)] 10362K->8948K(19968K), 0.0009356 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
    23. [Full GC (System.gc()) [PSYoungGen: 504K->0K(6144K)] [ParOldGen: 8444K->710K(13824K)] 8948K->710K(19968K), [Metaspace: 2958K->2958K(1056768K)], 0.0057077 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
    24. */
    25. //根据日志
    26. System.gc();
    27. }
    28. }

    看一下打印出的GC日志:

    [GC (System.gc()) [PSYoungGen: 2918K->488K(6144K)] 11110K->9263K(19968K), 0.0009433 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (System.gc()) [PSYoungGen: 488K->0K(6144K)] [ParOldGen: 8775K->1008K(13824K)] 9263K->1008K(19968K), [Metaspace: 3356K->3356K(1056768K)], 0.0050389 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    Heap
     PSYoungGen      total 6144K, used 56K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
      eden space 5632K, 1% used [0x00000000ff980000,0x00000000ff98e2b8,0x00000000fff00000)
      from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
      to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
     ParOldGen       total 13824K, used 1008K [0x00000000fec00000, 0x00000000ff980000, 0x00000000ff980000)
      object space 13824K, 7% used [0x00000000fec00000,0x00000000fecfc110,0x00000000ff980000)
     Metaspace       used 3363K, capacity 4500K, committed 4864K, reserved 1056768K
      class space    used 366K, capacity 388K, committed 512K, reserved 1048576K

    看样子是执行了两次GC,分析一下各个的含义:

    [PSYoungGen: 2918K->488K(6144K)] 11110K->9263K(19968K), 0.0009433 secs]

    PSYoungGen,从young这个词就可以看出来,这个是新生代。

    6144K,当年新生代可用空间为6144K。即一个survior+Eden的区域大小。

    2918K->488K,代表了原先由新生代有2918K的内存占用,GC后剩下的488K。回收了2M,没毛病。

    19968K,代表的是整体的堆内存空间,新生代默认是整体堆空间的1/3,这里大致看起来确实是。

    11110K->9263K,代表了堆整体从11110K回收到了9263K。

    后面的时间就是消耗时间了。

    后面的这个FullGC应该是我程序结束后,整体的一个FullGc.整体也可以看出来:

    PSYoungGen:新生代

    ParOldGen:老年代

    Metaspace:元空间

    垃圾回收回收的也主要是这几个区域。不过我分配了20M内存,如果换算的话,应该是20480K,但实际使用的只有19968K空间。其它的500多K的空间呢?

    因为初学,猜测是另一个不被使用的survior区域。但是,从大小来说,20480/3/10,我这面计算下682.6666666666667,比500要大了不少。而且元空间并不占堆内存。后期回来再看吧。

    言归正传,从2918K->488K(6144K)看出来,我们的两个对象还是被回收了。这里证明了引用计数法在java中其实并没有使用。

    2.2 可达性分析算法

    可达性分析算法,则是从定义的一些根对象(GCRoot)开始,搜索这些根对象直接或者间接所持有的对象,来形成一个个引用链。不在这些引用链上的对象,则代表没有其它对象持有,可以被回收。

    那么,可以用作GC ROOT节点有哪些?

    在虚拟机栈中(局部变量表)所引用的对象。

    在方法区中静态属性所引用的对象。

    在方法区中常量所引用的对象。

    在本地方法栈JNI中引用的对象。

    java虚拟机内部的引用,比如基础数据据类型对应的Class对象,常驻异常对象,以及系统类加载器。

    被同步锁所持有的对象。

    反应Java虚拟机内部情况的JMXBean,JVMTI注册的回调,本地代码缓存等。(这个没有懂)。

    其实在测试OOM导出的hprof文件,也可以看到GCROOT这一系列对象,当然,暂时没有深究,后期学完了统一串一下。

     

  • 相关阅读:
    CleanMyMac4.11.1中文完整语言版本
    实时时钟 RTC(2)
    二十、泛型(9)
    深度学习修炼(三)卷积操作 | 边界填充、跨步、多输入输出通道、汇聚池化
    SAP SEGW 事物码里的 ABAP 类型和 EDM 类型映射的一个具体例子
    Windows terminal美化工具Oh-My-Posh
    工作7年收集到的git命令
    java计算机毕业设计商场后台管理系统源码+系统+数据库+lw文档+mybatis+运行部署
    【51单片机】DS18B20(江科大)
    第三次工业革命(四)
  • 原文地址:https://blog.csdn.net/key_wu/article/details/126631642