zoukankan      html  css  js  c++  java
  • JVM-gcRoots 和 强引用,软引用, 弱引用, 虚引用, 代码演示和应用场景

    什么是垃圾? 什么是gcRoots, 谈谈你对 强, 软, 弱 , 虚引用的理解, 他们的应用场景

    jvm采用可达性分析法: 从gcRoots集合开始,自上向下遍历,凡是在引用链上的对象,都不是垃圾, 不在引用链上的对象就是垃圾,但此时不会马上被回收, 还需要进行二次标记, 第一次标记,判断当前对象是否有finalize()方法,并且该方法没有被执行过, 如果不存在就标记为垃圾, 等待回收, 如果有的话,进行第二次标记,第二次标记将当前对象放入F-Queue队列中, 并生成一个finalize线程取执行该方法, 虚拟机不保证该方法一定会执行, 这是因为如果线程执行缓慢或进入了死锁,会导致回收系统的崩溃, 如果执行了finalize()方法之后,仍然没有与GC Roots有直接或者间接的引用,则该对象就会被回收 当内存不足的时候,避免OOM,jvm会将这些垃圾回收

    gcRoots: 4类:
    1: native 方法引用的对象
    2: 栈中引用的对象(方法中引用的对象)
    3: 方法区中类静态变量 引用的对象(类中的 静态变量 引用的对象)
    4: 方法区中,常量引用的对象

    由于gcRoots 中关键是引用, 初始,只有引用 和 未引用之分, 但是随着业务复杂,比如缓存, 在内存充足的时候不需要垃圾回收,当内存不足的时候,才进行回收.... 逐渐细分为: 强, 软, 弱 , 虚引用

    软引用写缓存,演示:

      class MyCache<K,V>{
        private HashMap<K,SoftReference<V>>  cacheMap;
    
        public MyCache() {
            this.cacheMap = new HashMap<>();
        }
    
        // 添加缓存
        public void putValue(K key, V value){
            //这里注意: 放在cacheMap中的对象,最好不要在其他地方有引用,否则容易造成 StrongReference
            cacheMap.put(key,new SoftReference<V>(value));
        }
        // 取出缓存
        public V getValue(K key){
            V value = null;
            SoftReference<V> reference = cacheMap.get(key);
            if(reference != null){
                value = reference.get();
            }
            return value;
        }
    }
    

    class Test {
        public static boolean isRun = true;
        //虚引用 , 这个实际代码中用的很少,PhantomReference, 对一个 对象设置虚引用关联时,当这个对象被垃圾收集器回收时, 收到一个系统通知,
        //通常配合 ReferenceQueue使用
        //利用虚引用PhantomReference实现对象被回收时收到一个系统通知
        public static void main(String[] args) throws Exception {
            String abc = new String("abc");
            System.out.println(abc.getClass() + "@" + abc.hashCode());
            final ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
            new Thread() {
                public void run() {
                    while (isRun) {
                        Object obj = referenceQueue.poll();
                        if (obj != null) {
                            try {
                                Field rereferent = Reference.class
                                        .getDeclaredField("referent");
                                rereferent.setAccessible(true);
                                Object result = rereferent.get(obj);
                                System.out.println("gc will collect:"
                                        + result.getClass() + "@"
                                        + result.hashCode() + "	"
                                        + (String) result);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }.start();
            PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc, referenceQueue);
            abc = null;
            Thread.currentThread().sleep(3000);
            System.gc();
            Thread.currentThread().sleep(3000);
            isRun = false;
        }
    }
  • 相关阅读:
    MySQL数据库之WHERE条件语句
    MySQL数据库的简单操作指令之DML语言
    课程设计必备之数据库操作代码模板
    MySQL数据库之外键约束的简单理解
    pdf.js的使用
    javascript连连看
    数据库问题
    列表文字超出后,鼠标悬浮显示全部内容
    springboot component注入servecie
    点击列表 获取table tr td 下的input value
  • 原文地址:https://www.cnblogs.com/lvcai/p/13601833.html
Copyright © 2011-2022 走看看