本文内容来自《深刻理解Java虚拟机》,主要是自身学习,用于记录重点,方便回忆,复习。对应《深刻理解Java虚拟机》第三章,记录GC的算法,特色,经常使用GC收集器。算法
虚拟机系列一:Java虚拟机以内存bash
垃圾回收器的主要做用是回收无用的对象空间,那么怎么判断对象是否已经无用了呢??主要有两种算法。多线程
对象增长一个计数器,当有引用(变量)指向该对象是,计数器加一,但引用再也不指向该对象,计数器减一,计数器为0便可回收。Java虚拟机未使用该方法,主要是因为该方法很难解决循环应用问题。以下:并发
class GcTest{
Object obj;
public static void main(){
GcTest objA = new GcTest(); GcTest objB = new GcTest();
objA.obj = objB; objB.obj = objA;
objA = null;
objB = null;
//此种状况下使用,应用计数法,对象objA,objB的计数均为1,未能被回收
}
}复制代码
从CG Roots出发,向下搜索,所走过的路径称为引用链,当一个对象没有在任何引用链上,则此对象可被回收。post
GC Roots的对象包括如下引用:学习
(1)虚拟机栈(方法中局部变量指向的引用)中引用的对象。spa
(2)方法区中类静态属性引用的对象。线程
(3)方法区中常量引用的对象。code
(4)本地方法区栈中JNI应用的对象。对象
补充:
可达性分析不可达的对象不会当即被回收,还得进过两次标记过程。一、第一次标记为筛选对象是否必要执行finalize()方法(对象没有覆盖finalize,或已经执行过则为非必要)。二、若是1结果为必要,则放入F-Queue队列中,虚拟机会创建低优先机线程调用,不保证必定执行完finalize(是对象最后的复活机会)。
相似Object obj = new Object(),不会被垃圾回收器回收。
有用但非必须的对象,在系统将要发生内存溢出前,把这些对象列进回收范围,进行第二次回收。经过SofeReference类实现。
非必须对象,强度比软引用弱,发生垃圾回收,不管内存是否足够,都会回收对象。经过WeakReference实现
幽灵引用、幻影引用,最弱的一种引用。惟一的用处是,垃圾回收时会收到一个系统通知,经过PhantomReference实现。
标记出内存中可被回收的对象,回收相应的对象。主要有两个不足:一、效率问题,标记、清除效率都不高。二、空间碎片化,会有大量不连续的内存碎片。
将内存划分为大小相等的两块、一块为空闲面,一块为对象面。回收是减对象面中不能被回收的对象复制到空闲面,清除对象面内全部对象。此时的清除后的块为空闲面。使用于对象存活率低场景,少许复制,清除全部空间。
对不能被回收的对象进行标记,整理到连续的空间上,清除掉余下空间。
采用分代收集算法,把Java堆分为年轻代、老年代。年轻代中每次回收都只有少许对象存活,适用“复制算法”。老年代存活率高、适用标记整理算法。
年轻代中分为Eden区,还有两块Survivor区。
每次建立对象,使用Eden区及一块Survivor区。当垃圾回收时,将对象复制到另外一块Survivor区,清除该Eden区及Survivor区数据。HotSpot虚拟机默认Eden:Survivor大小比例为8:1,也就是一块Survivor只有空间10%,回收时,当Eden区大量对象存活时,Survivor明显放不下。这时对象会被放入老年区。
进入老年区除以上状况还有,Survivor区中数据通过15次(默认,可配置)垃圾回收,仍未被回收,会将对象放入老年区。
新生代垃圾收集器: Serial(1) ParNew(2) Parallel Scavenage(3)
老年代垃圾收集器: CMS(可配合的新生的收集器为一、2) Serial Old(可配合的新生的收集器为一、二、3) Parallel Old(可配合的新生的收集器为3)
单线程收集器,工做时,必须暂停其余全部工做线程。Client模式下的默认年轻代(新生代)收集器,简单高效。
Serial收集器的多线程版,指定参数-XX:UseConcMarkSweepGC选项后,默认新生代收集器就会是ParNew,经过-XX:ParallelGCThreads限制垃圾收集器线程数。
吞吐量(运行用户代码时间/cpu时间(垃圾收集器工做时间+用户代码运行时间))优先的收集器。适合后台运算而不须要太多交互任务。-XX:MaxGCPauseMillis控制垃圾收集器最大停顿时间,-XX:GCTimeRatio((0,100)整数,工做时间/垃圾时间,如19 ,则工做时间占比为19/19+1 )吞吐量大小。-XX:+UseAdaptiveSizePolicy虚拟机会根据系统状况自动调整各参数。
serial的老年代收集器,单线程、标记-整理算法。
Parallel Scavenage,多线程、标记-整理算法,吞吐量优先。
追求停顿时间短、标记-清除算法、过程包括:
一、初始化标记(Stop The World 中止工做线程)
二、并发标记
三、从新标记(Stop The World 中止工做线程)
四、并发清除
缺点:标记-整理算法,容易碎片化。
配置参数
-XX:+UseCMSCompactAtFullCollection ,顶不住,须要Full GC时开启内存合并整理。
-XX:+CMSFullGCsBeforeCompaction 设置多少次不压缩的Full GC后进行GC压缩,默认为0,即每次Full GC都进行碎片整理。
复制+标记-整理,总体复制-整理算法,局部复制算法