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());
    }
}

运行结果

相关推荐
阿伟*rui2 小时前
jvm入门
jvm
学点东西吧.5 小时前
JVM(五、垃圾回收器)
jvm
请你打开电视看看8 小时前
Jvm知识点
jvm
程序猿进阶8 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
阿龟在奔跑20 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
王佑辉21 小时前
【jvm】方法区常用参数有哪些
jvm
王佑辉21 小时前
【jvm】HotSpot中方法区的演进
jvm
Domain-zhuo21 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
Theodore_10222 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则
我是苏苏2 天前
Web开发:ORM框架之使用Freesql的DbFrist封装常见功能
java·前端·jvm