文章目录
垃圾回收
以前的垃圾回收机制
1.引用计数法
每个创建出来的对象通过某种方法记录他被引用的数量,当引用的数量变为0时,说明该对象已经没有人去使用,回收该对象
缺点:
当两个对象互相引用时,那么无论这两个对象被不被使用都不会触发垃圾回收机制

2.可达性分析算法
如果一个对象直接或者间接的被根对象(GC Root)引用那么这个对象不用被回收
根对象
一定不会被当成垃圾回收的对象
实现步骤
1.Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
2.扫描堆中的对象,看是否能够沿着 GC Root对象 为起点的引用链找到该对象,找不到,表示可以回收
哪些对象可以作为 GC Root ?
1.系统类

2.操作系统引用的java对象

3.被加锁的对象
4.正在活动的线程中局部变量引用的对象

4种引用
1.强引用
只有所有 GC Roots 对象都不通过(强引用)引用该对象,该对象才能被垃圾回收

2.软引用(SoftReference)
仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用对象可以配合引用队列来释放软引用自身**(两次垃圾回收)**

3.弱引用(WeakReference)
仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象可以配合引用队列来释放弱引用自身**(一次垃圾回收)**

4.虚引用(PhantomReference)(直接内存地址)
必须配合引用队列使用,主要配合 ByteBuffffer 使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存

5.终结器引用(FinalReference)(不建议使用)
无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 fifinalize方法,第二次 GC 时才能回收被引用对象

软引用使用场景
在内存空间比较紧张时,一些占用空间较大而又不是很重要的资源就可以使用软引用声明,在内存不足时可以将这些软引用声明的资源回收
例如
我们堆内存中只有20MB的大小,现在要连续声明5个大小为4Mb的不重要的对象,如果我们想要程序执行结束的优先级高于不重要的对象被回收,那么这个代码一定会造成堆溢出(因为是强引用)

堆内存不足:
优化:
使用软引用来存储对象,这样在内存紧张时可以通过Full GC (Allocation Failure)将软引用回收

当内存不足时系统会逐步进行垃圾回收,第一次GC回收无用的新生代对象,第二次GC回收无用的老年代对象,第三次回收与第一次回收类似,第四次回收软引用的新年代和老年代对象,此时内存足够进行下一次操作,垃圾回收结束
结果:
可以看出垃圾回收时将先前声明为软引用的四个对象全部回收了
弱引用使用场景
和软引用使用场景类似,也是当内存不足时将一些占用空间较大而又不是很重要的资源就可以使用弱引用声明,区别在于在GC阶段就会回收弱引用对象
弱引用声明
public static void main(String[] args) {
// list --> WeakReference --> byte[]
List<WeakReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
list.add(ref);
for (WeakReference<byte[]> w : list) {
System.out.print(w.get()+" ");
}
System.out.println();
}
System.out.println("循环结束:" + list.size());
}