强引用 当对象不再被引用时才会被GC回收
软引用 当内存空间被占满自动被回收
弱引用 引用值可以获取,JVM发生GC即被回收
虚引用 引用值无法获取,JVM发生GC即被回收,发生fullGC回收引用会被队列检测
直接看案例,先写个main方法
public class ReferenceMain {
int a = 0;
public ReferenceMain(int a){
this.a = a;
}
public ReferenceMain(){
}
//四种引用 强软弱虚
public static void main(String[] args) throws Exception {
// MainInferface m = new HardReference();
// MainInferface m = new SoftRefer();
MainInferface m = new WeakRefer();
m.mainMethod();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize" + a);
}
}
interface MainInferface {
void mainMethod() throws Exception;
}
强引用 当对象不再被引用时才会被GC回收
class HardReference implements MainInferface{
@Override
public void mainMethod() throws Exception{
ReferenceMain rm = new ReferenceMain();
System.gc();
System.out.println("有没回收");
rm = null;
System.gc();
}
}
输出
有没回收
finalize0
软引用 当内存空间被占满自动被回收
常用于缓存
class SoftRefer implements MainInferface{
@Override
public void mainMethod() throws Exception {
SoftReference<byte[]> sr = new SoftReference(new byte[1024*1024*600]);
System.out.println(sr.get());
System.gc();
System.out.println(sr.get());//没被回收
byte[]a = new byte[1024*1024*600];
System.out.println(sr.get());//自动回收
}
}
输出
[B@2503dbd3
[B@2503dbd3
null
弱引用 JVM发生GC即被回收
ThreadLocal 线程池 session等会用到
ThreadLocal原理:当起一个线程,调用threadLocal.set时会在内存中新建一个map对象(new ThreadLocalMap)
当前线程中的ThreadLocal引用 保存在 Thread.ThreadLocalMap中Entry.key(弱引用)中
当前线程创建多个ThreadLocal 则ThreadLocalMap中保存多个key
当前线程强引用ThreadLocal,当不再引用ThreadLocal时,对象被GC回收,Entry.key值为null,若非弱引用则key值为null的entry可能会造成内存泄露
调用threadLocal.remove则 value 会被GC回收,不调用且当前线程一不结束value值可能会造成内存泄漏
当前线程结束则ThreadLocalMap中所有key value 都会被GC回收
class WeakRefer implements MainInferface {
ThreadLocal<ReferenceMain> threadLocal = new ThreadLocal<>();
@Override
public void mainMethod() throws Exception {
WeakReference<ReferenceMain> wr = new WeakReference<ReferenceMain>(new ReferenceMain());
System.out.println(wr.get());
System.gc();
System.out.println(wr.get());
//ThreadLocal弱引用
new Thread(()->{
ThreadLocal<ReferenceMain> key2 = new ThreadLocal<>();
threadLocal.set(new ReferenceMain(1));
key2.set(new ReferenceMain(11));
System.out.println(threadLocal.get());
threadLocal.remove();
System.gc();
}).start();
System.gc();
new Thread(()->{
threadLocal.set(new ReferenceMain(2));
System.out.println(threadLocal.get());
}).start();
java.util.concurrent.TimeUnit.SECONDS.sleep(1);
System.out.println(threadLocal.get());
System.gc();
java.util.concurrent.TimeUnit.SECONDS.sleep(1);
}
}
输出
com.util.pattern.ReferenceMain@2503dbd3
null
finalize0
com.util.pattern.ReferenceMain@737b4956
finalize1
com.util.pattern.ReferenceMain@38b245e1
null
finalize2
finalize11
虚引用 引用值无法获取,JVM发生GC即被回收,发生fullGC回收引用会被队列检测
netty中io管理堆外内存会用到,当引用被回收JVM控制清除操作系统中对应的内存空间
class PhantomRefer implements MainInferface{
ReferenceQueue<ReferenceMain> QUEUE = new ReferenceQueue<>();
@Override
public void mainMethod() throws Exception {
PhantomReference<ReferenceMain> pr = new PhantomReference(new ReferenceMain(),QUEUE);
System.out.println(pr.get());
System.out.println(QUEUE.poll());
for (int i=0;i<100;i++) {
System.gc();
Reference reference= QUEUE.poll();
if (reference != null) {
System.out.println("GC次数:"+i +" 回收引用:" + reference);
break;
}
}
}
}
输出
null
null
finalize0
GC次数:5 回收引用:java.lang.ref.PhantomReference@2503dbd3