吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1065|回复: 3
收起左侧

[Java 转载] java中的引用类型

[复制链接]
18780334870 发表于 2021-1-11 10:22
Java中4种引用的级别由高到低依次为:
强引用  >  软引用  >  弱引用  >  虚引用

[Java] 纯文本查看 复制代码
class M {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize");
    }
}



强引用:
(只有指定m = null;时才进行回收)
[Java] 纯文本查看 复制代码
// 下列代码就是一个强引用
M m = new M();




软引用
(作用:非常适合缓存使用)
[Java] 纯文本查看 复制代码
// 运行下面代码的时候需要指定命令行参数(堆最大值20M):-Xmx20M
// 下面的代码会分配一个10M的空间,然后前两次get()都可以正常获取到
// 然后实例化一个强引用的15M的数组,这个时候就会内存泄漏
SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
System.out.println(m.get());
System.gc();
try {
    Thread.sleep(500);
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println(m.get());
// 再分配一个数组,heap将装不下,这时候系统会垃圾回收(启动的时候java会占用一部分内存),先回收一次,如果不够,会把软引用干掉
byte[] b = new byte[1024*1024*10];
System.out.println(m.get());




弱引用
(结论:只要垃圾回收器看到了就直接回收,与软引用区别:软引用是内存不够了才进行回收)
[Java] 纯文本查看 复制代码
WeakReference<M> m = new WeakReference<>(new M());
// M对象
System.out.println(m.get());
System.gc();
// null,调用了finalize()方法
System.out.println(m.get());




虚引用
(作用:在NIO中,就运用了虚引用管理堆外内存。)
(特点:无法通过虚引用来获取对一个对象的真实引用。)
(要求:必须和一个队列结合使用,除了写类库的人,一般没人用)

“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。你声明虚引用的时候是要传入一个queue的。当你的虚引用所引用的对象已经执行完finalize函数的时候,就会把对象加到queue里面。你可以通过判断queue里面是不是有对象来判断你的对象是不是要被回收了【这是重点,让你知道你的对象什么时候会被回收。因为对普通的对象,gc要回收它的,你是知道它什么时候会被回收】。


[Java] 纯文本查看 复制代码
// 运行下面代码的时候需要指定命令行参数(堆最大值20M):-Xmx20M
// 虚引用必须与ReferenceQueue一起使用,当GC准备回收一个对象,如果发现它还有虚引用,就会在回收之前,把这个虚引用加入到与之关联的ReferenceQueue中。
ReferenceQueue<M> queue = new ReferenceQueue<>();
List<byte[]> bytes = new ArrayList<>();
// 虚引用
PhantomReference<M> reference = new PhantomReference<>(new M(),queue);
new Thread(() -> {
    for (int i = 0; i < 100; i++) {
        bytes.add(new byte[1024 * 1024]);
    }
}).start();

new Thread(() -> {
    while (true) {
        Reference<? extends M> poll = queue.poll();
        if (poll != null) {
            System.out.println("虚引用被回收了:" + poll);
        }
    }
}).start();
try {
    System.in.read();
} catch (IOException e) {
    e.printStackTrace();
}


简单分析一下上述代码:

第一个线程往集合里面塞数据,随着数据越来越多,肯定会发生GC。
第二个线程死循环,从queue里面拿数据,如果拿出来的数据不是null,就打印出来。


从运行结果可以看到:当发生GC,虚引用就会被回收,并且会把回收的通知放到ReferenceQueue中。

免费评分

参与人数 5吾爱币 +9 热心值 +5 收起 理由
厌亦 + 1 + 1 谢谢@Thanks!
丶沐箐 + 1 + 1 我很赞同!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
左手凯 + 1 + 1 用心讨论,共获提升!
alittlebear + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jacker 发表于 2021-1-11 10:34
感谢分享。
左手凯 发表于 2021-1-11 11:09
回忆童年快乐 发表于 2021-1-11 11:23
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-12 09:57

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表