每天一个面试题:四种引用,弱引用防止内存泄漏
创始人
2024-03-23 06:51:17
0

每天一个面试题:四种引用

  • 四种引用基本介绍
  • 实例Demo
    • - 虚引用
    • 弱引用防止内存泄漏
    • 弱引用
  • Debug分析源码

开始全新的学习,沉淀才会有产出,一步一脚印!
面试题系列搞起来,这个专栏并非单纯的八股文,我会在技术底层的基础上,不至于Debug,还会做一些实例的实现,实现一些简单的Demo,或者用于我做过的项目中去;
代码会同步在我的gitee中去,觉得不错的同学记得一键三连求关注,感谢:
链接: Reference

四种引用基本介绍

  • 强引用就是正常的new实例,这种关系是单独一对一的,由GCroot的引用链确定,不会被GC自动回收,需要手动收回;

在这里插入图片描述

  • 软引用,是基于SoftReference确定的,类似于代理加工实现,首次gc不回收,内存不足回收
    软参考对象,由垃圾自行决定清除收集器响应内存需求。 软引用最常被用来实现内存敏感型缓存 public class SoftReference extends Reference {

  • 弱引用:只要gc就删除
    在这里插入图片描述

  • 虚引用:配合了一个队列进行使用,gc去将虚引用的对象及其外部资源回收掉
    在这里插入图片描述

实例Demo

- 虚引用


public class TestPhantomfegerence {static class MyResource extends PhantomReference{//继承了虚引用类,构造方法中对应了 构造的 对象和队列public MyResource(String referent, ReferenceQueue q) {super(referent, q);}public void  clean(){System.out.println("clean");}}

进行测试

    public static void main(String[] args) {ReferenceQueue queue = new ReferenceQueue<>();List list = new ArrayList<>();list.add(new MyResource(new String("a"), queue));list.add(new MyResource("b", queue));list.add(new MyResource(new String("c"), queue));//调用系统GCSystem.gc();try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}Object obj;
//       gc后,如果存在资源,就打印,可以看到new的对象被打印了while((obj = queue.poll())!=null){if(obj instanceof MyResource ){((MyResource) obj).clean();}}}}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

弱引用防止内存泄漏

ThreadLocalMap中存在内存泄漏问题,这里可以通过一下这种方式实现


public class TestWeakReference {public static void main(String[] args) {MyweakMap map = new MyweakMap(5);map.put(0, new String("a"), "1");map.put(1, ("b"), "2");map.put(2, ("c"), "3");map.put(3, new String("d"), "3");System.out.println(map);System.gc();System.out.println(map.get("a"));System.out.println(map.get("b"));System.out.println(map.get("c"));System.out.println(map.get("d"));map.clean();System.out.println(map);}
    static class MyweakMap{static ReferenceQueue queue = new ReferenceQueue<>();static class Entry extends WeakReference {String value;//这里的value设定,让key成为了一个弱引用,value成强引用public Entry(String key, String value) {super(key,queue);this.value = value;}@Overridepublic String toString() {return "Entry{" +"value='" + value + '\'' +'}';}}
 

这里是通过判断当前的key是否为null来进行的

        public void clean(){Object object;while((object=queue.poll())!=null){for (int i = 0; i < table.length; i++) {if(table[i]==object){table[i]=null;}}}}

如果为null,就将当前table,也就是对象Entry[]对应的单个Entry直接设置为null, static class Entry extends WeakReference { 这就断开了联系
在这里插入图片描述

        public MyweakMap(int init){table= new Entry[init];}Entry[] table;public void put(int index, String key, String value){table[index] = new Entry(key, value);}public String get(String key){for(Entry entry : table){if(entry!=null){String k = entry.get();if(k!=null&&k.equals(key)){return entry.value;}}}return null;}@Overridepublic String toString() {return "MyweakMap{" +"table=" + Arrays.toString(table) +'}';}}}

在这里插入图片描述

弱引用

public class TestSoft {static class WeakReferenceDemo extends WeakReference {public WeakReferenceDemo(String referent) {super(referent);System.out.println(referent);}}public static void main(String[] args) {List list = new ArrayList<>();list.add(new TestSoft.WeakReferenceDemo(new String("a")));list.add(new TestSoft.WeakReferenceDemo(("b")));list.add(new TestSoft.WeakReferenceDemo(new String("c")));System.out.println(list.get(0).get());System.gc();System.out.println(list.get(0).get());}
}

结果展示 a b c a null

Debug分析源码

引用的底层很简单

public class WeakReference extends Reference {public WeakReference(T referent) {super(referent);}public WeakReference(T referent, ReferenceQueue q) {super(referent, q);}}

一个泛型类

public abstract class Reference {private T referent;         /* Treated specially by GC */volatile ReferenceQueue queue;

链表结构

    @SuppressWarnings("rawtypes")Reference next;transient private Reference discovered;  /* used by VM */static private class Lock { };private static Lock lock = new Lock();private static Reference pending = null;
 

实现了一个静态内部类ReferenceHandler

  private static Lock lock = new Lock();

加载一个类锁

    private static class ReferenceHandler extends Thread {ReferenceHandler(ThreadGroup g, String name) {super(g, name);}public void run() {for (;;) {Reference r;synchronized (lock) {if (pending != null) {r = pending;pending = r.discovered;r.discovered = null;} else {try {try {lock.wait();} catch (OutOfMemoryError x) { }} catch (InterruptedException x) { }continue;}}// Fast path for cleanersif (r instanceof Cleaner) {((Cleaner)r).clean();continue;}ReferenceQueue q = r.queue;if (q != ReferenceQueue.NULL) q.enqueue(r);}}}static {ThreadGroup tg = Thread.currentThread().getThreadGroup();for (ThreadGroup tgn = tg;tgn != null;tg = tgn, tgn = tg.getParent());Thread handler = new ReferenceHandler(tg, "Reference Handler");/* If there were a special system-only priority greater than* MAX_PRIORITY, it would be used here*/handler.setPriority(Thread.MAX_PRIORITY);handler.setDaemon(true);handler.start();}public T get() {return this.referent;}public void clear() {this.referent = null;}public boolean enqueue() {return this.queue.enqueue(this);}/* -- Constructors -- */Reference(T referent) {this(referent, null);}Reference(T referent, ReferenceQueue queue) {this.referent = referent;this.queue = (queue == null) ? ReferenceQueue.NULL : queue;}}                
            
            
            
            
            
            

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...