java中四种引用,强软弱虚
-
强引用:
只要有引用指向某个对象,这个对象就不会被回收=====这个就是最普通的new Object()
-
软引用:
这个可以用在缓存中,数据都放在里面,允许内存不够的情况下把这个数据释放掉
@Test
public void tet1() throws InterruptedException {
SoftReference<byte[]> sr = new SoftReference<>(ByteBuffer.allocate(1024 * 1024 *10).array());
System.out.println(sr.get());
// System.gc();
TimeUnit.SECONDS.sleep(1);
System.out.println(sr.get());
ByteBuffer.allocate(1024 * 1024 * 15);
System.out.println(sr.get());
}
结果:
[B@6b57696f
[B@6b57696f
null
-
弱引用:
只要遇到了gc,就直接回收
作用在于:只要有一个强引用指向了这个对象,那么托管就交给了那个强引用。只要强引用“不关心”这个对象了,那么弱引用也就可以直接被回收掉
####一般用在容器里面
ThreadLocal
threadlocal存储本次线程变量,独享资源。
set(object)的时候,以这个threadlocal作为key,将这个key和value放入到map中
其中map中的key使用的是弱引用。在这个情况下,只要是强引用消失了,map中的key也消失掉了。
坑:虽然key弱引用消失了,但是value是强引用,只有在线程销毁的时候才会消失,所以如果不停的往threadlocalmap里面放值,那么value的强引用就一直在,可能造成oom
所以,使用完必须使用remove方法,防止内存泄露
WeakHashMap
首先看一下它创建entry的代码
从这里我们可以看到其内部的Entry继承了WeakReference,也就是弱引用,所以就具有了弱引用的特点。不过还要注意一点,那就是ReferenceQueue,他的作用是GC会清理掉对象之后,引用对象会被放到ReferenceQueue中。
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
final int hash;
Entry<K,V> next;
/**
* Creates new entry.
*/
Entry(Object key, V value,
ReferenceQueue<Object> queue,
int hash, Entry<K,V> next) {
// key是弱引用,但是value不是
// 同时传入了一个referenceQueue队列,被垃圾回收掉的Entry会放入到这个引用队列里面
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}
}
当gc发生,强引用失效的部分,会被放入队列。然后不管是请求put(),get(),还是size()等等方法,都会调用到到expungeStaleEntries()方法,这个方法会将entry的value=null,方便gc回收
/**
* Expunges stale entries from the table.
*/
private void expungeStaleEntries() {
for (Object x; (x = queue.poll()) != null; ) {
synchronized (queue) {
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) x;
int i = indexFor(e.hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> p = prev;
while (p != null) {
Entry<K,V> next = p.next;
if (p == e) {
if (prev == e)
table[i] = next;
else
prev.next = next;
// Must not null out e.next;
// stale entries may be in use by a HashIterator
e.value = null; // Help GC
size--;
break;
}
prev = p;
p = next;
}
}
}
}
-
虚引用
基本上用不到。虚引用 使用的是堆外内存,不会被jvm所管理,用来管理堆外内存使用的。
弱引用使用get()方法还是可以拿到对应的值的,但是到虚引用的时候get()什么都拿不到。
netty会使用堆外内存,所以可能会用到