1、什么对象会被认为是垃圾对象?
一般一个对象不再被引用,就代表该对象可以被回收,标记垃圾对象的方式引用计数算法、可达性分析算法。
引用计数算法:这种算法是通过一个对象的引用计数器来判断该对象是否被引用了。每当对象被引用,引用计数器就会加 1;每当引用失效,计数器就会减 1。当对象的引用计数器的值为 0 时,就说明该对象不再被引用,可以被回收了。这里强调一点,虽然引用计数算法的实现简单,判断效率也很高,但它存在着对象之间相互循环引用的问题
可达性分析算法:GC Roots 是该算法的基础,GC Roots 是所有对象的根对象,在 JVM 加载时,会创建一些普通对象引用正常对象。这些对象作为正常对象的起始点,在垃圾回收时,会从这些 GC Roots 开始向下搜索,当一个对象到 GC Roots 没有任何引用链相连时,就证明此对象是不可用的。目前 HotSpot 虚拟机采用的就是这种算法。
可作为GC Root对象:
a、Java虚拟机栈中的引用的对象
b、方法区中的类静态属性引用的对象
c、方法区中的常量引用的对象
d、本地方法栈中JNI的引用的对象
2、什么时候会触发对象回收?
垃圾回收线程在 JVM 中是自动执行的,Java 程序无法强制执行。我们唯一能做的就是通过调用 System.gc 方法来"建议"执行垃圾收集器,但是否可执行,什么时候执行?仍然不可预期
3、垃圾回收发生在什么地方?
在JVM 的内存区域中,程序计数器、虚拟机栈、本地方法栈都是线程私有的,随着线程的创建而创建,销毁而销毁;每个栈帧中分配多少内存基本是在类结构确定下来的时候就已知的,因此这三个区域的内存分配和回收都具有确定性。垃圾回收的重点区域是堆和方法区中的内存
4、怎么进行垃圾回收的?
Java 提供了一个系统级的线程来跟踪每一块分配出去的内存空间,当 JVM 处于空闲循环时,垃圾收集器线程会自动检查每一块分配出去的内存空间,然后自动回收每一块空闲的内存块。
5、垃圾回收算法
6、基于垃圾回收算法的垃圾回收器
GC 吞吐量 = GC耗时 / (应用程序耗时 +GC 耗时),GC 的吞吐量一般不能低于 95%
停顿时间:指垃圾收集器正在运行时,应用程序的暂停时间
垃圾回收频率:指多久发生一次指垃圾回收,通常垃圾回收的频率越低越好,增大堆内存空间可以有效降低垃圾回收发生的频率,但同时也意味着堆积的回收对象越多,最终也会增加回收时的停顿时间
垃圾收集器的种类很多,可以分成响应速度快、吞吐量高两种类型。通常情况下 CMS 和 G1 回收器的响应速度快,Parallel Scavenge 回收器的吞吐量高。
垃圾回收器对比
a、G1收回器
G1 将整块内存区域分配成若干同等大小 reg,新生代和老年代均由不同数量的reg组成
垃圾回收算法:标记整理,可规避cms内存碎片化问题,大大降低了fullGC的频率,虽然常态性能略输于cms但却没有cms特殊情况下的极端性能问题,总体更稳定。G1中各代的内存区域里reg间不一定是连续的,所以对于cpu缓存加载机制并不是特别友好,而且大对象占据超过一个reg时还会带来内存浪费的问题。
使用场景:可配分内存空间比较大(8g+),保证每个reg分配的尽量大,以减少内存浪费
优势:G1主要采用的是将堆内存分为多个相同大小的region,利用 Region Set进行对象引用收集,维护了一个优先列表,当进行垃圾回收时,根据停断时间,选择最优的region进行垃圾回收,
1、并行与并发:G1能够更充分利用多CPU、多核环境运行
2、分代收集:G1虽然也用了分代概念,但相比其他收集器需要配合不同收集协同工作,但G1收集器能够独立管理整个堆
3、空间管理:与CMS的标记一清理算法不同,G1从整体上基于标记一整理算法,将整个Java堆划分为多个大小相等的独立区域(Region),这种算法能够在运行过程中不产生内存碎片
4、可预测的停顿:降低停顿时间是G1和CMS共同目标,但是G1追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集器上的时间不得超过N毫秒。
7、什么情况会发生stw ?
只要发生GC就会触发 stop the world,区别只是时间的长短。而stw时间主要受垃圾回收器影响 比如:Serial、PartNew、Parallel Scavenge 收集器无论是串行还是并行,都会挂起用户线程,而CMS和G1在并发标记时,是不会挂起用户线程,但其他时候一样会挂起用户线程,stop the world的时间相对来说小很多了。
full gc将会对年轻代、老年代以及元空间、堆外内存进行垃圾回收。
触发Full GC的原因:
a、当年轻代晋升到老年代的对象大小比目前老年代剩余的空间大小还要大时,此时会触发Full GC;
b、当老年代的空间使用率超过某阈值时,此时会触发Full GC;
c、当元空间不足时(JDK1.7永久代不足),也会触发Full GC;
d、当调用System.gc()也会安排一次Full GC;
8、查看和分析GC
a、JVM配置GC的常用的参数
-XX:+PrintGC 输出 GC 日志
-XX:+PrintGCDetails 输出 GC 的详细日志
-XX:+PrintGCTimeStamps 输出 GC 的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出 GC 的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在进行 GC 的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的输出路径查看命令:
jinfo -flags 进程ID
总结:在 JDK1.8 环境下,默认使用的是 Parallel Scavenge(年轻代)+Serial Old(老年代)垃圾收集器(标记清除算法)
垃圾回收器官网地址:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/index.html



