前言
这篇文章记录笔者Java学习中的问题思考
一、Java四种引用
四种引用分为以下的类型
- 强引用: 强引用指的是通过new对象创建的引用,垃圾回收器即使是内存不足也不会回收强引用指向的对象。
- 软引用: 软引用是通过SoftRefrence实现的,它的生命周期比强引用短,在内存不足,抛出OOM之前,垃圾回收器会回收软引用引用的对象。软引用常见的使用场景是存储一些内存敏感的缓存,只有当内存不足时会被回收。
- 弱引用: 弱引用是通过WeakRefrence实现的,它的生命周期比软引用还短,GC只要扫描到弱引用的对象就会回收。弱引用常见的使用场景也是存储一些内存敏感的缓存。
- 虚引用: 虚引用是通过FanttomRefrence实现的,它的生命周期最短,随时可能被回收。如果一个对象只被虚引用引用,我们无法通过虚引用来访问这个对象的任何属性和方法。它的作用仅仅是保证对象在finalize后,做某些事情。虚引用常见的使用场景是跟踪对象被垃圾回收的活动,当一个虚引用关联的对象被垃圾回收器回收之前会收到一条系统通知。
二、相关案例
1.强引用&&软引用
package com.qjy.javabasicpractice.string.reference;
import com.qjy.javabasicpractice.string.bean.Employee;
import org.junit.Test;
import java.lang.ref.SoftReference;
import java.util.LinkedList;
import java.util.List;
public class ReferenceTest {
@Test
public void testSoftReference(){
Employee employee = new Employee();//调用无参构造函数,自动为相关属性赋值
SoftReference<Employee> employeeSoftReference = new SoftReference<>(employee);
employee=null;
System.out.println(employeeSoftReference.get().getName());//使用弱引用访问对象属性
System.gc();//进行垃圾回收
System.out.println("After Gc::");//使用弱引用访问对象属性
System.out.println(employeeSoftReference.get().getName());//使用弱引用访问对象属性
//向堆中填充数据模拟OOM
List<Byte[]> list = new LinkedList<>();
try{
for (int i = 0; i < 100; i++) {
System.out.println("SoftReference == "+employeeSoftReference.get());
list.add(new Byte[1*1024*1024]);
}
}catch (Throwable e){
System.out.println("Exception is "+employeeSoftReference.get());
e.printStackTrace();
}
}
}
输出结果:
可以看到这里将强引用本身设置为Null并不会对软引用造成干扰;
同时调用GC垃圾回收机制在堆内存充足时也不对内存造成干扰,只有当堆内存不存时,在抛出OOM之前,垃圾回收器才会去回收软应用的内存
2.弱引用
@Test
public void testWeakReference(){
Employee employee = new Employee();//调用无参构造函数,自动为相关属性赋值
WeakReference<Employee> employeeSoftReference = new WeakReference<>(employee);
System.out.println(employeeSoftReference.get());//使用弱引用访问对象属性
employee=null;
System.gc();
System.out.println(employeeSoftReference.get());//使用弱引用访问对象属性
}
执行结果
总结
软引用在实际开发中一般用来做缓存,例如一个程序用来处理用户提供的图片,将图片全部置于内存中,虽然可以提高图片的访问速度,但是会占据大量的内存;这种情况下可以用软引用构造一块内存,而后当内存不足时,会对其进行回收
弱引用一般用于需要使用的内存,但这块内存回收时并不会对APP运行产生多大的影响,实际过程中一般用于应对Activity内存泄漏问题
虚引用一般用来收集对象的回收信息,不会单独使用,使用虚引用指向对象,并不能通过虚引用拿到其对象内部的数值,但是当gc进行回收时,会将回收信息和对象绑定起来,最终得到一个回收时的通知。