介绍
最近读了周志明先生写的深入理解jvm,不敢说理解有多深。总结以供回顾。
自动内存管理机制
对象是否已死
- 可达性分析算法
判断对象是否存活的算法是这样的:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则
证明此对象是不可用的。此外,这里没有使用引用记数算法,因为很难解决对象之间相互引用的关系。
垃圾收集算法
标记-清除(Mark-Sweep)算法
- 效率不高;标记清除之后会产生大量空间碎片,导致提前触发一下次GC
首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象
复制算法
- 实现简单,运行高效。代价是把内存缩小为了原来的一半
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面然后再把已使用过的内存空间一次清理掉。
标记-整理算法
标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
分代收集算法
根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集都发现有大批对象死去,只有少量存活,那就选用复制算法。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须用“标记-清理”或者“标记-整理”算法来进行回收。
常见垃圾收集器
- 串行 Serial 单线程的一个回收器,简单,易实现,效率高
- 并行 ParNew Serial的多线程版,可以充分的利用cpu的资源,减少回收的时间
- 吞吐量优先 Parallel Scavenge,侧重于吞吐量的控制
- 并发标记清除 CMS concurrent mark sweep 一种以获取最短回收停顿时间为目标的回收器,该回收器基于标记-清除算法
CMS GC
- 初始标记,仅仅标记一下GC Roots能直接关联到的对象,速度很快
- concurrent-mark 并发标记,由前段标记过的绿色对象出发,所有可达到的对象都在本阶段标记
- 重新标记(修正并发标记期间因用户程序继续用作而导致标记产生变动的那一部分对象的标记记录),暂停所有用户线程,重新扫描用户堆对象,进行可达性分析。注意,当前阶段以新生代对象为根来判断对象是否存活
- 并发清理,进行并发的垃圾清理
常用优化
- 如果应用存在大量的短期对象,应该选择较大的年轻代;如果存在相对较多的持久对象,老年代应该适当增大。
- CMS提供CMSScavengeBeforeRemark参数,用来保证Remark前强制进行一次Minor GC
- 通过把-XX:PermSize参数和-XX:MaxPermSize设置成一样,强制虚拟机在启动的时候就把永久代的容量固定下来,避免运行时自动扩容
- CMS默认情况下不会回收Perm区,通过参数CMSPermGenSweepingEnabled、CMSClassUnloadingEnabled ,可以让CMS在Perm区容量不足时对其回收
G1 GC
- 初始标记———>并发标记———>最终标记———>清理回收
- 并行与并发;分代收集;空间整理;可预测的停顿;运行期间不会产生内存空间碎片;它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region的集合
region
每个region被标记成eden, old, survivor, humongous,其中humongous代表巨型对象。
region大小设置 -XX:G1HeapRegionSize ,1,2,4,8,32M,默认值是堆的大小/2048
yong gc
一般对象均在eden区分配内存,除了humongous对象,当所有eden区域被耗尽内存时,触发yong gc,活跃对象copy到survivor区和old区中,空闲的region会被放入空闲列表
-XX:MaxGCPauseMillis 设置G1收集过程目标时间,默认值200ms
-XX:G1NewSizePercent 新生代最小值,默认值5%
-XX:G1MaxNewSizePercent 新生代最大值,默认值60%
mixed gc
触发机制:当老年代的大小占整个堆大小百分比达到该阀值时,会触发一次mixed gc
执行过程:参考cms执行过程。类似。会优先考虑收益高的old区域执行gc。
full gc
如果对象内存分配过快,mixed gc来不及执行,导致年轻代被占满,就会触发full gc,serial old gc,导致长时间的暂停时间。
参数
UseSerialGC:
client模式下,采用serial+serial Old组合
UseParNewGC:
常用ParNew+Serial Old组合
UseConcMarkSweepGC:
常用ParNew+CMS+Serial Old
UseParallelGC:
采用Parallel Scavenge+serial Old收集器
UseParallelOldGC:
采用Parallel Scavenge+Parallel Old组合