@lzb1096101803
2016-03-08T17:36:29.000000Z
字数 1860
阅读 586
电话面试
http://chenchendefeng.iteye.com/blog/455883
Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。对虚拟机栈,程序计数器等随线程随生随灭的不需要,主要是对堆进行回收
至于回收算法,有复制算法,标记整理,标记清除和分代收集算法
为了提高效率
对堆进行分区,不同分区采用不同的回收算法,其实就是分代收集算法
为了减少回收频率,堆被划分为新生代,老年代和永久代
又可细分为eden,survior from,to, Tenured,Perm
其中比例默认为8:1:1
基于回收次数的不同,新生代采用复制算法,老年代采用标记整理算法。
Java虚拟机要如何判断什么对象需要回收
不是用引用计数法,而是使用可达性分析算法,脱离GC Roots的且在finalize函数中未被挽回的对象会被回收,GC Roots对象可以是本地变量表的引用的对象,方法区的引用的对象等
在Hotspot中,需要减少GC停顿,如果要逐个检查引用会花费不少时间
采用OopMap数据结构直接得知哪些地方存放对象引用,扫描时直接得知信息
不是所有地方都能停下来GC,需要有安全点,对长时间执行特征的程序作为安全点,线程采用主动式中断方式访问GC标识。安全区域的对象也可以回收(可能因为没有分配CPU而需要标记)
GC有两种类型:Scavenge GC和Full GC。
1. Scavenge GC
一般情况下,当新对象生成,并且在Eden申请空间失败时,就好触发Scavenge GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。
2. Full GC
对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:
* Tenured被写满
* Perm域被写满
* System.gc()被显示调用
* 上一次GC之后Heap的各域分配策略动态变化
主流的是使用G1收集器
CMS 收集器与 G1 收集器的特点。
Serial(串行GC)收集器
Serial收集器是一个新生代收集器,单线程执行,使用复制算法。它在进行垃圾收集时,必须暂停其他所有的工作线程(用户线程)。是Jvm client模式下默认的新生代收集器。
ParNew(并行GC)收集器
ParNew收集器其实就是serial收集器的多线程版本
Parallel Scavenge(并行回收GC)收集器
Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行多线程收集器
CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而parallel Scavenge收集器的目标则是达到一个可控制的吞吐量。吞吐量= 程序运行时间/(程序运行时间 + 垃圾收集时间),虚拟机总共运行了100分钟。其中垃圾收集花掉1分钟,那吞吐量就是99%。
Serial Old(串行GC)收集器
Serial Old是Serial收集器的老年代版本,它同样使用一个单线程执行收集,使用“标记-整理”算法。
Parallel Old(并行GC)收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
CMS(并发GC)收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于“标记-清除”算法实现的,整个收集过程大致分为4个步骤:
①.初始标记(CMS initial mark)
②.并发标记(CMS concurrenr mark)
③.重新标记(CMS remark)
④.并发清除(CMS concurrent sweep)
CMS收集器的优点:并发收集、低停顿,但是CMS还远远达不到完美
CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。
使用“标记-清除”算法收集后,会产生大量碎片。
G1收集器
G1收集器基于“标记-整理”算法实现
收集的范围都是整个新生代或老年代,而G1将整个Java堆(包括新生代,老年代)
对象优先分配在Eden。大对象进入老年代。长期存活的对象进入老年代,动态对象年龄判定,空间份额担保