聊聊GC

聊聊GC

1.为什么java需要GC?

GC是垃圾收集的意思(Gabage Collection),当一个对象不能再被后续程序所引用到时,这个对象所占用的内存空间就没有存在的意义了,java虚拟机会不定时的去检测内存中这样的对象,然后回收这块内存空间。用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

2.GC是发生在什么时候?

参考:GC在什么时候,对什么东西,做了什么事情

3.有哪几种垃圾收集器,一般怎么配置使用?

参考:GC算法

4.GC算法(如何判断一个对象可以被回收)?

一、引用计数算法:

  判断对象的引用数量:

    通过判断对象的引用数量来决定对象是否可以被回收;

    每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1;

    任何引用计数为0的对象实例可以被当作垃圾收集;

  优缺点:

    优点:执行效率高,程序执行受影响较小;

    缺点:无法检测出循环引用的情况,导致内存泄漏;

二、可达性分析算法:

  通过判断对象的引用链是否可达来决定对象是否可以被回收;

  可以作为GC Root的对象有:

    虚拟机栈中引用的对象(栈帧中的本地变量表);

    方法区中的常量引用对象;

    方法区中类静态属性引用对象;

    本地方法栈中JNI(Native方法)的引用对象;

    活跃线程中的引用对象;

5.为什么年轻代要划分Eden区,survivor区?

参考:survivor区存在意义

6.为什么需要分代垃圾回收?

分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。
在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的
Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。但是还有一些对象,主要
是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系
统会产生大量的这些对象,有些对象甚至只用一次即可回收。
试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会
长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有
效果的,因为可能进行了很多次遍历,但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划

分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。

7.引用的分类?

一,强引用

Java中默认声明的就是强引用,比如:

1
2
Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收
obj = null; //手动置null

只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了。

二,软引用

软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
在 JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

三,弱引用

弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

四,虚引用

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示,