目录:
- 我的疑问
- 什么是GC,为什么要有GC
- 四种引用对象
我的疑问:
- 什么是垃圾回收。
- 回收什么东西。
- 怎样回收。
- 如何回收。
本节解决前两个问题,什么是垃圾回收,回收什么东西。
什么是GC,为什么要有GC:
GC(Gabage Collection),是垃圾回收的意思。
我们知道向c、c++是需要手动回收内存的,但因为内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃。
所以java作为高级语言当然会帮我忙实现了自动回收内存啦,回收那些不再使用的对象释放内存。
那java是如何判断对象不再使用的呢?
这里使用了一个叫做GC Roots的东西,它其实就是一个对象的引用的集合,一个对象的所有引用都在此中。
判断对象不再使用还有一个专业的名词叫做可达性分析,不再使用的依据就是通过GC Roots Tracing辨别。
也就是说以GC Roots为起点,从起点开始依次往下检索,检索的路径称为ReferenceChain,当GC Roots与ReferenceChain没有任何对象相连时则表示无对象引用。
在Java语言中,可作为GC Roots的对象包括下面几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象。
- 本地方法栈中JNI(即一般说的Native方法)引用的对象。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象。
四种引用对象:
前面说到了可达性分析是通过GC Roots来分析的,而GC Roots其实就是对象引用的集合,那么你知道对象有哪几种引用嘛,待我一一道来。
在JDK 1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、 软引用(Soft Reference)、 弱引用(Weak Reference)、 虚引用(Phantom Reference)4种,且这4种引用强度依次逐渐减弱。
1、强引用:
强引用就是我们日常开发中最常使用的Object obj = new Object(),强引用最大的特点就是不会被GC,即使内存不够了也不会GC,会抛出OutOfMemory。
如果你想中断强引用也很简单,只需要obj = null即可(Effective In Java中也提到了,如果你确定此对象不再使用请将其赋为null)。
1 public class StrongRef { 2 3 public static void main(String[] args) { 4 Object obj = new Object(); 5 // 即使创建array时溢出也不会回收obj对象 6 int[] array = new int[1000000]; 7 } 8 9 }
2、软引用:
软引用对于强引用来说使用场景比较少,一般只会在底层源码或框架中才会使用。
用来描述一些还有用但并非必需的对象,系统会在即将发生OutOfMemory之前将这些应用纳入回收范围内进行二次回收,如果内存还不够才会抛出OutOfMemory。
1 public class SoftRef { 2 3 public static void main(String[] args) { 4 Object obj = new Object(); 5 SoftReference<Object> softRef = new SoftReference<>(obj); 6 // obj值为null,等待GC 7 obj = null; 8 // 重新从弱引用中获取obj示例,如果此前发生了GC则值为null 9 Object softObj = softRef.get(); 10 System.out.println(softObj == null); 11 } 12 13 }
3、弱引用:
若应用较之软引用更弱一些,只能存活到下一次GC之前,GC时无论内存够不够都会回收弱引用。
1 public class WakeRef { 2 3 public static void main(String[] args) { 4 WeakReference<Person> reference = new WeakReference<>(new Person("张三", 20)); 5 // 此刻还能获取到person 6 System.out.println(reference.get()); 7 // 通知JVM回收资源 8 System.gc(); 9 // GC后person=null 10 System.out.println(reference.get()); 11 12 } 13 14 } 15 16 class Person { 17 18 public String name; 19 public int age; 20 21 public Person(String name, int age) { 22 this.name = name; 23 this.age = age; 24 } 25 26 @Override 27 public String toString() { 28 return "[name:" + name + ",age:" + age + "]"; 29 } 30 31 }
4、虚引用:
也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。
一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。
为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
1 public class PhantomRef { 2 3 public static void main(String[] args) { 4 ReferenceQueue<String> queue = new ReferenceQueue<>(); 5 PhantomReference<String> phantomRef = new PhantomReference<>(new String("hello"), queue); 6 // 即使没有被GC调值还是为null 7 System.out.println(phantomRef.get()); 8 } 9 10 }