JVM(HotSpot):GC之垃圾标记阶段

文章目录

前言

我们从日常生活中应该知道,当我们去打扫一间屋子时,首先,你要判断那些事垃圾,然后,对其进行清除打扫。不然,把重要物品也给清除了,不是亏大了。

JVM垃圾回收器,也是这么工作的。

你可以把GC看作JVM这个屋子的清洁员。

那么,在打扫之前,需要精确的标记出哪些对象是垃圾对象,从而,为清理阶段做准备。

一、标记阶段算法

1、引用计数法

定义:一个对象,如果被引用了,那么,它就不能标记为垃圾,不能回收。

缺点 :存在内存泄漏问题。

当两个垃圾对象互相引用时,无法回收。

2、可达性分析算法(JVM使用)

定义 :对象直接或间接的被GC Root对象引用。则不能标记为垃圾。

哪些是GC Root对象

一般地

​ a、虚拟机栈中引用的对象

​ b、本地方法栈中引用的对象

​ c、方法区中静态变量引用的对象

​ d、字符串常量池中引用的对象

​ e、被sync锁把持的对象

​ f、局部回收和分代收集时候,产生的临时性GC Roots

二、4种引用

为什么要学习5中引用?

这个是在特定情况下,符合可达性分析算法时,依然要被回收的对象。

其中,软引用,弱引用,虚引用,终结器引用,它们也是对象,也占用着内存空间。

这几种引用,一般要结合引用队列进行回收处理。

终结器引用,无需手动编码。了解即可。

1、 强引用

​ 就是new出来的对象,即使内存不够了,也不能回收,会导致OOM

2、软引用(SoftReference)

​ 缓存技术常使用,内存不够了,才会回收相应的对象,它可以获取对象实例的方法和属性

可以配合引用队列来释放软引用自身

3、弱引用(WeakHashMap)

​ 内存够的情况下,只要GC发现,就会回收,它可以获取对象实例的方法和属性

可以配合引用队列来释放软引用自身

4、虚引用(PhantomReference)

​ 内存足够的情况下,只要GC就会被回收,无法获取对象实例的方法和属性,在于跟踪垃圾回收的过程

必须配合引用队列来释放软引用自身

三、代码案例

1、 强引用

运行参数设置

JVM内存大小设置为20M

bash 复制代码
-Xmx20m
java 复制代码
    private static final int _4MB = 4 * 1024 * 1024;
    public static void main(String[] args) throws IOException {
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new byte[_4MB]);
        }
        System.in.read();
    }

运行结果

2、软引用(SoftReference)

运行参数设置

JVM内存大小设置为20M,打印GC回收信息

bash 复制代码
-Xmx20m -XX:+PrintGCDetails -verbose:gc

大致引用关系: list --> SoftReference --> byte[]

java 复制代码
    public static void soft() {
        List<SoftReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());

        }
        System.out.println("循环结束:" + list.size());
        for (SoftReference<byte[]> ref : list) {
            System.out.println(ref.get());
        }
    }

运行结果:没有发生OOM错误,触发了Full GC


使用引用队列,回收软引用

java 复制代码
public class Demo2_4 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList<>();

        // 引用队列
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }

        // 从队列中获取无用的 软引用对象,并移除
        Reference<? extends byte[]> poll = queue.poll();
        while( poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }

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

    }
}

运行结果:软引用被GC回收了。

3、弱引用(WeakHashMap)

运行参数设置

JVM内存大小设置为20M,打印GC回收信息

bash 复制代码
-Xmx20m -XX:+PrintGCDetails -verbose:gc
java 复制代码
public class Demo2_5 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        //  list --> WeakReference --> byte[]
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
            list.add(ref);
            for (WeakReference<byte[]> w : list) {
                System.out.print(w.get()+" ");
            }
            System.out.println();

        }
        System.out.println("循环结束:" + list.size());
    }
}

运行结果

相关推荐
高山上有一只小老虎4 小时前
使用Memory Analyzer (MAT)分析内存溢出
java·jvm
ss2734 小时前
自定义线程池:从工作原理到实战验证
java·开发语言·jvm
sinat_2554878111 小时前
文件I/O流
java·jvm·算法
鸿蒙开发工程师—阿辉11 小时前
HarmonyOS 5 数据持久化:关系型数据库 (RelationalStore)
jvm·数据库·harmonyos
步步为营DotNet11 小时前
深度剖析.NET中WeakReference的内存管理机制:优化资源使用与避免内存泄漏
java·jvm·.net
没有bug.的程序员12 小时前
Ribbon vs LoadBalancer 深度解析
jvm·后端·spring cloud·微服务·ribbon·架构·gc调优
没有bug.的程序员1 天前
Nacos vs Eureka 服务发现深度对比
jvm·微服务·云原生·容器·eureka·服务发现
xing-xing1 天前
JVM 内存、直接内存、系统内存、本地内存、物理内存总结
java·jvm
是一个Bug1 天前
JVM基础50道经典面试题(一)
jvm
我居然是兔子1 天前
Java虚拟机(JVM)内存模型与垃圾回收全解析
java·开发语言·jvm