为什么要GC
Java不像C++一样,对于在堆上申请的空间需要调用free或者delete这样手动释放,而是使用gc来进行自动的释放,对于一个应用程序来说,给定的堆的空间是一定的,如果无限的申请但是不释放的话,就会导致oom,因此gc很重要。
什么需要被GC
和c++一样,在堆上申请的内存空间的对象需要在一个合适的时间释放,回想在C++中的智能指针,往往就是在对某个对象的引用计数为0时执行析构函数释放对应的内存,java中也是一样,当对于某个对象的引用为0时会被gc。
Java的引用对象
-
强引用
一般情况下声明的都是强引用,例如:
Person person = new Person();
注意这里的new Person()是一个对象,是在堆上分配了一定内存大小的,而person是指向它的引用,这里就是强引用。
对于一个对象来说,只要有强引用指向它的话,系统是肯定不会对它执行gc的。所以如果在一个函数中如上正常创建一个对象的话,只有在函数执行完之后,该对象才回被gc,因为变量person的生命周期到头了,就没有指向Person对象的引用了。对于全局变量来说,如果想释放它的话,就需要将person = null,这样也会去掉该对象的引用。
-
弱引用
弱引用的声明如下
WeakReference<Person> weakref = new WeakReference<>(person);
这样就会将指向Person对象的引用变为弱引用了
Person person = weakref.get()
这样又会转换为强引用
对于一个对象来说,如果它的所有引用都是弱引用的话就会被立刻gc
-
软引用
软引用的声明如下
SoftReference<Person> softref = new SoftReference<>(person)
转为强引用的方法如上
对于一个对象来说,如果它的所有引用都是软引用且当前内存空间不足时,系统会对其gc
- 虚引用
虚引用需要和ReferenceQueue联合使用,具体如下
ReferenceQueue rq = new ReferenceQueue();
PhantomReference<Person> phantomref = new PhantomReference<>(person,rq);
关于ReferenceQueue还需要再研究一下,网上说可以用来实现当某个对象被gc时的通知,未完。