1、GC怎么判断对象是否可回收

引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数
为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。
可达性分析(Reachability Analysis):从GC Roots开始向下搜索,搜索所走过的路径称为引用
链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,不可达对象。

2、GC常用算法

GC最基础的算法有三种: 标记 -清除算法(缺点是碎⽚化)、复制算法(缺点是浪费空间)、标记-压缩算法(效率⽐前两者差),我们常用的垃圾回收器一般都
采用分代收集算法。
标记 -清除算法:“标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两
个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
复制算法:“复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只
使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已
使用过的内存空间一次清理掉。
标记-压缩算法:标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清
理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存 。
分代收集算法:“分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,⽼年代⼀般使⽤“标记-清除”、“标记-整理”算法,年轻代⼀般⽤复制算法。


3、GC在堆内存的工作过程

当 Eden 区的空间满了, Java虚拟机会触发⼀次 Minor GC,以收集新⽣代的垃圾,存活下来 的对象,
则会转移到 Survivor区。 ⼤对象(需要⼤量连续内存空间的Java对象,如那种很⻓的字符串)直接进⼊⽼年态; 如果对象在 Eden出⽣,并经过第⼀次Minor GC后仍然存活,并且被Survivor容纳的话,年龄 设为1,每熬过⼀次
Minor GC,年龄+1,若年龄超过⼀定限制(15),则被晋升到⽼年态。即 ⻓期存活的对象进⼊⽼年
态。 ⽼年代满了⽽⽆法容纳更多的对象,Minor GC 之后通常就会进⾏Full GC,Full GC 清理整个 内存堆 –
包括年轻代和年⽼代。 Major GC 发⽣在⽼年代的GC,清理⽼年区,经常会伴随⾄少⼀次Minor GC,⽐Minor GC慢 10倍以 上。


4、GC的回收器(CMS和G1)

CMS收集器,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的
收集器。
G1收集器,G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量
内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。


5、Java中4种引用及区别

(1)强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

(2)软引用(SoftReference)
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

(3)弱引用(WeakReference)
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

(4)虚引用(PhantomReference)
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。


6、final、finally与finalize的区别

final 用于声明属性,方法和类,分别表示属性不可变,方法不可重写,类不可继承。内部类要访问
局部变量,局部变量必须定义成final类型。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此
方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用


7、哪些可以作为GC ROOTS

GC Roots 包括:
Java 线程中,当前所有正在被调⽤的⽅法的引⽤类型参数、局部变量、临时值等。也就是与我 们栈帧相关的各种引⽤。
所有当前被加载的 Java 类。
Java 类的引⽤类型静态变量。
运⾏时常量池⾥的引⽤类型常量(String 或 Class 类型)。
JVM 内部数据结构的⼀些引⽤,⽐如 sun.jvm.hotspot.memory.Universe 类。
⽤于同步的监控对象,⽐如调⽤了对象的 wait() ⽅法。
JNI handles,包括 global handles 和 local handles。
这些 GC Roots ⼤体可以分为三⼤类,下⾯这种说法更加好记⼀些:
活动线程相关的各种引⽤。
类的静态变量的引⽤。
JNI 引⽤。
有两个注意点:
我们这⾥说的是活跃的引⽤,⽽不是对象,对象是不能作为 GC Roots 的。
GC 过程是找出所有活对象,并把其余空间认定为“⽆⽤”;⽽不是找出所有死掉的对象,并回 收它们占
⽤的空间。所以,哪怕 JVM 的堆⾮常的⼤,基于 tracing 的 GC ⽅式,回收速度也会⾮常快。


8、GC相关参数-调优的制作

收集器设置:
-XX:+UseSerialGC 设置串行收集器
-XX:+UseParallelGC 设置并行收集器
-XX:+UseParalledlOldGC 设置并行年老代收集器
-XX:+UseConcMarkSweepGC 设置并发收集器
垃圾回收统计信息:
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename 日志输出到文件里filename,比如:-Xloggc:/gc.log
并行收集器设置:
-XX:ParallelGCThreads=n 设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n 设置并行收集最大暂停时间
-XX:GCTimeRatio=n 设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:MaxGCPauseMillis=n设置并行收集最大暂停时间
并发收集器配置:
-XX:+CMSIncrementalMode 设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n 设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

9、熟悉常见垃圾收集的特征和作用范围

年轻代:serial GC、parNew GC、paraller Scavenge GC
老年代:serial old GC 、paraller old GC、CMS