java引用类型
强引用
Object o = new Object();
- 但凡这个对象在任何一个地方被使用,java 的gc 必然不会回收这个对象
- 就算显式调用了gc 方法也不行,因为jvm 认为这个对象还会被使用
public static void main(String[] args) throws InterruptedException, IOException {
Object g = 10;
System.gc();
System.in.read();
System.out.println(g);
}
软引用
- 当一个对象被一个软引用指定时,只有系统内存不够用时才会回收该对象。
public static void main(String[] args) throws InterruptedException, IOException {
SoftReference soft = new SoftReference(new byte[1024 * 1024 * 30]);
System.out.println(soft.get());
System.gc();
Thread.sleep(1000);
byte[] b = new byte[1024 * 1024 * 15];
System.out.println(soft.get());
}
- 如上他被回收了
- 他需要被SoftReference 包装
- 主要用与当缓存,比如数据库缓存
弱引用
public static void main(String[] args) throws InterruptedException, IOException {
byte[] bytes = new byte[1024 * 1024 * 30];
WeakReference soft = new WeakReference(bytes);
System.out.println(soft.get());
System.gc();
System.out.println(soft.get());
ThreadLocal<byte[]> threadLocal = new ThreadLocal<>();
threadLocal.set(bytes);
}
- 只要发生gc 就会被回收。
- 使用场景 如果这个弱引用的对象 在一个强引用中,只要这个强引用小时,这个弱引用就会被自动回收。
- 一般是用在容器中。
- ThreadLocal 就是一个弱引用
- 原因是如果ThreadLocal 是一个强引用并且他指向了另一个引用,并且那个对象是长驻内存的,这个ThreadLocal 就无法被正常回收。
- 但是对于ThreadLocal 必须要调用remove 方法
- 原因是:当 threadlocal 使用完后,将栈中的 threadlocal 变量置为 null,threadlocal 对象下一次 GC 会被回收,那么 Entry 中的与之关联的弱引用 key 就会变成 null,如果此时当前线程还在运行,那么 Entry 中的 key 为 null 的 Value 对象并不会被回收(存在强引用),这就发生了内存泄漏,当然这种内存泄漏分情况,如果当前线程执行完毕会被回收,那么 Value 自然也会被回收,但是如果使用的是线程池呢,线程跑完任务以后放回线程池(线程没有销毁,不会被回收),Value 会一直存在,这就发生了内存泄漏。value还有引用的原因是threadlocalMap 指向了value
虚引用