1.java对象引用类型
https://blog.csdn.net/weixin_31884015/article/details/114082371
强引用(不被回收) > 软引用(内存不足的时候会被回收) > 弱引用(随时都可以被回收) > 虚引用(只能在ReferenceQueue引用队列中见到)
1.1.强引用
public A a = new A();
a的值就是强引用,强引用是不会被回收的,且强引用中局部变量也是不会被回收的
1.2.软引用(SoftReference)
SoftReference<A> reference = new SoftReference<A>(a);
reference 引用对象a就是软引用
被a对象包起来的b对象实例就是软引用,正常状态是不会去回收软引用对象的
直到快要溢出的时候才会去回收软引用对象
实际案例:
假如有一个应用需要读取大量的本地数据(图片、通讯率、临时文件等):
如果每次读取数据都从硬盘读取则会严重影响性能,
如果一次性全部加载到内存中又可能造成内存溢出。
此时使用软引用可以解决这个问题。
设计思路是:用一个HashMap来保存数据的路径和相应数据对象关联的软引用之间的映射关系,在内存不足时,
JVM会自动回收这些缓存数据对象所占用的空间,从而有效地避免了OOM的问题。
MapimageCache=new HashMap();
1.3.弱引用(WeakReference)
1)不管空闲内存是否足够都会被回收器回收
public static void main(String[] args) {
Object obj1= new Object();//建立弱引用
WeakReference softRefer = new WeakReference<>(obj1);//观察内存地址
System.out.println("obj1=" +obj1);
System.out.println("softRefer=" +softRefer.get());//obj1创建可以回收的条件
obj1 = null;//gc回收
System.gc();//再次观察内存地址
System.out.println("obj1=" +obj1);
System.out.println("softRefer=" +softRefer.get());
}
结果是会被gc回收掉
2)WeakHashMap也是弱引用
public static void main(String[] args) throws InterruptedException {
hashMapMethod();
System.out.println("--------华丽的分割线--------");
weakHashMapMethod();
}
/*** HashMap测试(强引用)*/
private static void hashMapMethod() {
HashMap map = new HashMap<>();
String key= "key1";
String value= "HashMap-value";
map.put(key, value);
System.out.println(map);
key= null;
System.out.println(map);
System.gc();
System.out.println(map);
}
/*** 若引用(WeakHashMap测试)*/
private static void weakHashMapMethod() throws InterruptedException {
WeakHashMap map = new WeakHashMap<>();//注意这里的new一个字符串与直接写key="key2"对测试结果是有区别的,详细原因可以看之前讲的内存分配
String key = new String("key2");
String value= "WeakHashMap-value";
map.put(key, value);
System.out.println(map);
key= null;
System.out.println(map);
System.gc();
System.out.println(map);
}
结果WeakHashMap的值会被gc回收掉
3)ReferenceQueue引用队列
public static void main(String[] args) throws InterruptedException {
Object obj1= new Object();
ReferenceQueue referenceQueue = new ReferenceQueue();//当GC释放对象内存的时候,会将引用加入到引用队列
//弱引用
// WeakReference weakReference = new WeakReference<>(obj1, referenceQueue);
//软引用
SoftReference weakReference = new SoftReference<>(obj1,referenceQueue);
System.out.println(obj1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
System.out.println("--------华丽的分割线--------");
obj1= null;
System.gc();
Thread.sleep(500);
System.out.println(obj1);
System.out.println(weakReference.get());
System.out.println(referenceQueue.poll());
}
当GC释放对象内存的时候,会将引用加入到引用队列
1.4.虚引用(PhantomReference)
public static void main(String[] args) throws InterruptedException {
Object obj1= new Object();
ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference phantomReference = new PhantomReference<>(obj1,referenceQueue);
System.out.println(obj1);
System.out.println(phantomReference.get());
System.out.println(referenceQueue.poll());
System.out.println("--------华丽的分割线--------");
obj1= null;
System.gc();
Thread.sleep(500);
System.out.println(obj1);
System.out.println(phantomReference.get());
System.out.println(referenceQueue.poll());
}
2.finalize()方法
改方法属于Object中的,属于一个GC的后置处理器的功能.在被GC的前一刻执行
可以利用此方法来引用本身来逃脱被GC的命运
public static FinalizeGC obj1 = null;
/*** 重写finalize方法
*@throwsThrowable*/
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("执行finalize方法");//自救,在回收时建立引用链
FinalizeGC.obj1 = this;
}
public static void main(String[] args) throws InterruptedException {
obj1= new FinalizeGC();
obj1= null;
System.gc();
Thread.sleep(600);
System.out.println("第一次自救成功:"+obj1);
obj1= null;
System.gc();
Thread.sleep(600);
System.out.println("第二次自救失败,不会再次执行finalize方法:"+obj1);
}