聊聊GC
1.为什么java需要GC?
GC是垃圾收集的意思(Gabage Collection),当一个对象不能再被后续程序所引用到时,这个对象所占用的内存空间就没有存在的意义了,java虚拟机会不定时的去检测内存中这样的对象,然后回收这块内存空间。用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
2.GC是发生在什么时候?
3.有哪几种垃圾收集器,一般怎么配置使用?
参考:GC算法
4.GC算法(如何判断一个对象可以被回收)?
一、引用计数算法:
判断对象的引用数量:
通过判断对象的引用数量来决定对象是否可以被回收;
每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1;
任何引用计数为0的对象实例可以被当作垃圾收集;
优缺点:
优点:执行效率高,程序执行受影响较小;
缺点:无法检测出循环引用的情况,导致内存泄漏;
二、可达性分析算法:
通过判断对象的引用链是否可达来决定对象是否可以被回收;
可以作为GC Root的对象有:
虚拟机栈中引用的对象(栈帧中的本地变量表);
方法区中的常量引用对象;
方法区中类静态属性引用对象;
本地方法栈中JNI(Native方法)的引用对象;
活跃线程中的引用对象;
5.为什么年轻代要划分Eden区,survivor区?
6.为什么需要分代垃圾回收?
分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。
在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的
Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。但是还有一些对象,主要
是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系
统会产生大量的这些对象,有些对象甚至只用一次即可回收。
试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会
长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有
效果的,因为可能进行了很多次遍历,但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划
分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。
7.引用的分类?
一,强引用
Java中默认声明的就是强引用,比如:
1 | Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收 |
只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了。
二,软引用
软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。
三,弱引用
弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。
四,虚引用
虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示,