|
1 | 1 | 强引用、软引用、弱引用、虚引用 |
2 | 2 | === |
3 | 3 |
|
| 4 | +在JDK1.2以前的版本中,当一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及状态,程序才能使用它。这就像在日常生活中,从商店购买了某样物品后,如果有用,就一直保留它,否则就把它扔到垃圾箱,由清洁工人收走。一般说来,如果物品已经被扔到垃圾箱,想再把它捡回来使用就不可能了。 |
| 5 | +但有时候情况并不这么简单,你可能会遇到类似鸡肋一样的物品,食之无味,弃之可惜。这种物品现在已经无用了,保留它会占空间,但是立刻扔掉它也不划算,因为也许将来还会派用场。对于这样的可有可无的物品,一种折衷的处理办法是:如果家里空间足够,就先把它保留在家里,如果家里空间不够,即使把家里所有的垃圾清除,还是无法容纳那些必不可少的生活用品,那么再扔掉这些可有可无的物品。 |
| 6 | +从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。 |
| 7 | + |
| 8 | +***这四种级别由高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用。*** |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +在java.lang.ref包中提供了三个类:SoftReference类、WeakReference类和PhantomReference类,它们分别代表软引用、弱引用和虚引用。ReferenceQueue类表示引用队列,它可以和这三种引用类联合使用,以便跟踪Java虚拟机回收所引用的对 象的活动。 |
| 15 | + |
| 16 | + |
| 17 | + |
4 | 18 | - 强引用(Strong Reference) |
5 | | - 平时我们编程的时候例如:`Object object=new Object()`;那`object`就是一个强引用了。如果一个对象具有强引用,那就类似于必不可少的生活用品, |
6 | | - 垃圾回收器绝不会回收它。当内存空 间不足,`Java`虚拟机宁愿抛出`OutOfMemoryError`错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。 |
| 19 | + |
| 20 | + 你懂的,不要胡乱持有着不放,不然内存泄露、oom有你好看,就像是老板(OOM)的亲儿子一样,在公司可以什么事都不干,但是千万不要老是占用公司的资源为他自己做事,记得用完公司的妹子之后,要让她们去工作(资源要懂得释放) 不然公司很可能会垮掉的。 |
7 | 21 |
|
| 22 | + 平时我们编程的时候例如:`Object object=new Object()`;那`object`就是一个强引用了。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当JVM的内存空间不足时,宁愿抛出OutOfMemoryError使得程序异常终止也不愿意回收具有强引用的存活着的对象!记住是存活着,不可能是你new一个对象就永远不会被GC回收。 |
| 23 | + |
8 | 24 | - 软引用(SoftReference) |
9 | | - 如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。 |
10 | | - 只要垃圾回收器没有回收它,该对象就可以被程序使用。**软引用可用来实现内存敏感的高速缓存**。 软引用可以和一个引用队列`(ReferenceQueue)`联合使用, |
| 25 | + |
| 26 | + 描述一些还有用,但并非必需的对象。如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存,但是system.gc对其无效,有点像老板(OOM)的亲戚,在公司表现不好有可能会被开除,即使你投诉他(调用GC)上班看片,但是只要不被老板看到(被JVM检测到)就不会被开除(被虚拟机回收)。 |
| 27 | + |
| 28 | +**软引用可用来实现内存敏感的高速缓存**。 软引用可以和一个引用队列`(ReferenceQueue)`联合使用, |
11 | 29 | 如果软引用所引用的对象被垃圾回收,`Java`虚拟机就会把这个软引用加入到与之关联的引用队列中。 |
12 | | - |
| 30 | + |
13 | 31 | - 弱引用(WeakReference) |
14 | | - 弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。 |
15 | | - 弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器 |
16 | | - 弱引用可以和一个引用队列`(ReferenceQueue)`联合使用,如果弱引用所引用的对象被垃圾回收,`Java`虚拟机就会把这个弱引用加入到与之关联的引用队列中。 |
17 | | - |
| 32 | + |
| 33 | + 同软引用,也用来描述非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。在对象没有其他引用的情况下,调用system.gc对象可被虚拟机回收,就是一个普通的员工,平常如果表现不佳会被开除(对象没有其他引用的情况下),遇到别人投诉(调用GC)上班看片,那开除是肯定了(被虚拟机回收)。 |
| 34 | + |
| 35 | + 在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了***只具***有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用最常见的用途是实现规范映射(canonicalizing mappings,比如哈希表)。 |
18 | 36 |
|
| 37 | + 常见的一个例子就是WeakHashMap,在HashMap中,键被置为null,唤醒gc后,不会垃圾回收键为null的键值对。但是在WeakHashMap中,键被置为null,唤醒gc后,键为null的键值对会被回收。 |
| 38 | + |
| 39 | + ``` |
| 40 | + public static void weakHashMapTest() { |
| 41 | + Integer key = new Integer(1); |
| 42 | + String value = "李四"; |
| 43 | + Map<Integer,String> weakHashMap = new WeakHashMap(); |
| 44 | + weakHashMap.put(key, value); |
| 45 | + System.out.println(weakHashMap);//{1=李四} |
| 46 | + key = null; |
| 47 | + System.gc(); |
| 48 | + System.out.println(weakHashMap);//{} |
| 49 | + } |
| 50 | + public static void hashMapTest() { |
| 51 | + HashMap<Integer,String> map = new HashMap<>(); |
| 52 | + Integer key = 1; |
| 53 | + String value = "张三"; |
| 54 | + map.put(key,value); |
| 55 | + System.out.println(map);//{1=张三} |
| 56 | + key = null; |
| 57 | + System.gc(); |
| 58 | + System.out.println(map);//{1=张三} |
| 59 | + } |
| 60 | + ``` |
| 61 | + |
19 | 62 | - 虚引用(PhantomReference) |
20 | | - "虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用, |
21 | | - 那么它就和没有任何引用一样,在 任何时候都可能被垃圾回收。 虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于: |
22 | | - 虚引用必须和引用队列 `(ReferenceQueue)`联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前, |
23 | | - 把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。 |
24 | | - 程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。 虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。 |
25 | | - 虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。 |
26 | | - 虚引用主要用于检测对象是否已经从内存中删除。 |
27 | | - |
28 | | - |
29 | | -有关弱引用以及软引用再分析一下: |
30 | | -我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型。这正是`Java`中弱引用和软引用的主要区别。 |
31 | | -如果一个对象只有弱引用指向它,垃圾回收器会立即回收该对象,这是一种急切回收方式。相对的,如果有软引用指向这些对象,则只有在`JVM`需要内存时才回收这些对象。 |
32 | | -弱引用和软引用的特殊行为使得它们在某些情况下非常有用。例如:软引用可以很好的用来实现缓存,当`JVM`需要内存时,垃圾回收器就会回收这些只有被软引用指向的对象。 |
33 | | -而弱引用非常适合存储元数据,例如:存储`ClassLoader`引用。如果没有类被加载,那么也没有指向`ClassLoader`的引用。一旦上一次的强引用被去除, |
34 | | -只有弱引用的`ClassLoader`就会被回收。 |
| 63 | + |
| 64 | + "虚引用"顾名思义,就是形同虚设,也成为幽灵引用或幻影引用,它是最弱的一种引用关系。就只是一个标识,对象的生命周期不受期影响,这货估计就是个临时工把,遇到事情的时候想到了你,没有事情的时候,秒秒钟拿出去顶锅,开除。 |
| 65 | + |
| 66 | + 一个对象是否有虚引用的存在完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一的用处:能在对象被GC时收到系统通知,主要用于跟踪对象何时被回收,比如防止资源泄漏等。 |
| 67 | + |
| 68 | + 虚引用必须和引用队列 `(ReferenceQueue)`联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。 虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null。 |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | + |
| 76 | + |
| 77 | + |
35 | 78 |
|
36 | 79 | --- |
37 | 80 |
|
|
0 commit comments