文章目录
- 前言
- 一、标记阶段算法
- 1、引用计数法
- 2、可达性分析算法(JVM使用)
- 二、4种引用
- 1、 强引用
- 2、软引用(SoftReference)
- 3、弱引用(WeakHashMap)
- 4、虚引用(PhantomReference)
- 三、代码案例
- 1、 强引用
- 2、软引用(SoftReference)
- 3、弱引用(WeakHashMap)
前言
我们从日常生活中应该知道,当我们去打扫一间屋子时,首先,你要判断那些事垃圾,然后,对其进行清除打扫。不然,把重要物品也给清除了,不是亏大了。
JVM
垃圾回收器,也是这么工作的。
你可以把GC
看作JVM
这个屋子的清洁员。
那么,在打扫之前,需要精确的标记出哪些对象是垃圾对象,从而,为清理阶段做准备。
一、标记阶段算法
1、引用计数法
定义:一个对象,如果被引用了,那么,它就不能标记为垃圾,不能回收。
缺点:存在内存泄漏问题。
当两个垃圾对象互相引用时,无法回收。
2、可达性分析算法(JVM使用)
定义:对象直接或间接的被GC Root对象
引用。则不能标记为垃圾。
哪些是GC Root对象
?
一般地
a、虚拟机栈中引用的对象
b、本地方法栈中引用的对象
c、方法区中静态变量引用的对象
d、字符串常量池中引用的对象
e、被sync锁把持的对象
f、局部回收和分代收集时候,产生的临时性GC Roots
二、4种引用
为什么要学习5中引用?
这个是在特定情况下,符合可达性分析算法时,依然要被回收的对象。
其中,软引用,弱引用,虚引用,终结器引用,它们也是对象,也占用着内存空间。
这几种引用,一般要结合引用队列
进行回收处理。
终结器引用,无需手动编码。了解即可。
1、 强引用
就是new出来的对象,即使内存不够了,也不能回收,会导致OOM
2、软引用(SoftReference)
缓存技术常使用,内存不够
了,才会回收相应的对象,它可以获取对象实例的方法和属性
可以配合引用队列来释放软引用自身
3、弱引用(WeakHashMap)
内存够的情况下,只要GC发现,就会回收,
它可以获取对象实例的方法和属性
可以配合引用队列来释放软引用自身
4、虚引用(PhantomReference)
内存足够的情况下,只要GC就会被回收,无法获取对象实例的方法和属性,在于跟踪垃圾回收的过程
必须配合引用队列来释放软引用自身
三、代码案例
1、 强引用
运行参数设置
JVM内存大小设置为20M
-Xmx20m
private static final int _4MB = 4 * 1024 * 1024;public static void main(String[] args) throws IOException {List<byte[]> list = new ArrayList<>();for (int i = 0; i < 5; i++) {list.add(new byte[_4MB]);}System.in.read();}
运行结果
2、软引用(SoftReference)
运行参数设置
JVM内存大小设置为20M,打印GC回收信息
-Xmx20m -XX:+PrintGCDetails -verbose:gc
大致引用关系: list --> SoftReference --> byte[]
public static void soft() {List<SoftReference<byte[]>> list = new ArrayList<>();for (int i = 0; i < 5; i++) {SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);System.out.println(ref.get());list.add(ref);System.out.println(list.size());}System.out.println("循环结束:" + list.size());for (SoftReference<byte[]> ref : list) {System.out.println(ref.get());}}
运行结果:没有发生OOM
错误,触发了Full GC
使用引用队列,回收软引用
public class Demo2_4 {private static final int _4MB = 4 * 1024 * 1024;public static void main(String[] args) {List<SoftReference<byte[]>> list = new ArrayList<>();// 引用队列ReferenceQueue<byte[]> queue = new ReferenceQueue<>();for (int i = 0; i < 5; i++) {// 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);System.out.println(ref.get());list.add(ref);System.out.println(list.size());}// 从队列中获取无用的 软引用对象,并移除Reference<? extends byte[]> poll = queue.poll();while( poll != null) {list.remove(poll);poll = queue.poll();}System.out.println("===========================");for (SoftReference<byte[]> reference : list) {System.out.println(reference.get());}}
}
运行结果:软引用被GC
回收了。
3、弱引用(WeakHashMap)
运行参数设置
JVM内存大小设置为20M,打印GC回收信息
-Xmx20m -XX:+PrintGCDetails -verbose:gc
public class Demo2_5 {private static final int _4MB = 4 * 1024 * 1024;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());}
}
运行结果