内存分配策略
以下内存分配策略适用于Serial/Serial Old收集器
新生代:
- -Xmn?M:分配新生代的大小。
- eden+survivor0+survivor1,比例默认为 eden:survivors=8:2,-XX:SurvivorRatio=?来调节比例值。
- 垃圾收集过程:
- 当eden区满时会进行Minor GC,GC的范围:eden,survivor0;
- Eden和survivor0中存活的对象进入survivor1;
- survivor0超过年龄阈值的会进入老年代,eden中存活的对象大于survivor0的容量,会进入老年代;
- 这个时候survivor0是空的,然后0和1会交换角色,下一次Minor GC将会继续重复以上操作。
- 对象年龄计数器:活过一个GC计数器便会加1,当超过一个最大值后对象会从survivor区进入老年代(默认值15,可用-XX:MaxTenuringThreshold来调节)
- 可以使用-XX:PrintGCDetails来打印GC回收日志。
- 采用 复制 算法。
老年代:
- 大对象直接进入老年代,如数组。-XX:PretenureSizeThreshold:决定大于多少M的对象会直接分配在老年代
- 采用 标记-整理 算法收集内存。
- 动态对象年龄判断:如果survivor中所有年龄相同大小的对象综合大于survivor的一半,那么大于或等于该年龄的对象会直接进入老年代。
- 空间分配担保:HandlePromotionFailure=true or false(开启或关闭)。
- 在Minor GC前,虚拟机会检查老年代所有连续空间是否大于新生代所有对象总空间;
- 如果成立那么Minor GC确保是安全的,否则会检查HandlePromotionFailure的值是否允许担保;
- 如果是,那么会继续检查老年代所有连续空间是否大于历次移动到老年代的对象的平均大小;
- 如果大于,则进行Minor GC;
- 如果小于或者HandlePromotionFailure的值不允许,则会进行Full GC。
方法区(永久代)
主要回收 废弃的常量 和 无用的类。
确定哪些对象该被回收
引用计数法
对象被引用时,加1,不被引用,减1,计数为0的对象不会在被使用,将会被回收。该方法无法解决循环的问题。
可达性分析法
- 通过GC roots的对象作为根节点,从这些点往下搜索,走过的路径为”引用链“,没有被任何引用链链接到的对象将被回收。
- Stop the world:因为在分析的过程中对象的关系时不断变化的,为了保证准确性,需要在某一时刻停止所有Java线程来检查对象的关系。
- OopMap:
- 安全点:线程会在某一个时间点停止程序进行GC(是否具有能让程序长时间执行的条件)
- 安全区域:
引用强度:
- 强引用:只要引用存在,对象将不会被回收。
- 软引用:可多活两个回合。
- 弱引用:可多活一个回合。
- 虚引用:不会对生存空间造成影响。
垃圾收集算法
标记-清除法
- 标记要清除对象
- 清除对象
- 产生很多碎片
复制算法
- 将存活的对象一次性复制到一个survivor中
- 清楚垃圾对象
- 不易产生碎片
标记-整理法
- 标记要垃圾对象
- 存活对象向一端移动
- 清理端边界以外的垃圾
- 不易产生碎片
垃圾收集器
Serial/Serial old
- Serial用于新生代,Serial Old用于旧生代
- 单线程收集器
- 使用复制算法
ParNew
- 多线程的Serial收集器
- 用于新生代
Parellel Scavenge/Parellel Old
- Parellel Scavenge适用于新生代,使用复制算法
- Parellel Old适用于老年代,使用标记-整理 算法
- 关注于控制吞吐量,又叫吞吐量优先处理器
- 吞吐量=运行代码时间/(运行代码时间+垃圾回收时间)
- -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间
-XX:GCTimeRatio:直接设置吞吐量大小- 适用于Serial收集器的各种参数,可使用-XX:+UseAdaptiveSizePolicy来动态分配新生代大小、Eden和Survivor的比例、晋升到老年代的对象的大小。
CMS(Current Mask Sweep)
- 使用标记-清楚算法,使用在老年代。
- 四个步骤:初始标记,并发标记,重新标记,并发清除。
- 初始标记:标记GC roots直接关联的对象,并发标记:进行引用追踪的过程,重新标记:修正之前并发标记时不断变化的引用关系,最后并发清除。
- 浮动垃圾问题:在并发清理的时候还会产生一些新的垃圾,可能出现“Current Mode Failure”失败而导致另一次Full GC。同时在垃圾收集进行的时候还需要一些内存供用户线程使用,所以CMS在并发收集时需要预留一些空间给程序使用,当老年代的使用量超过一个值时才会触发CMS。
- -XX:CMSInitiatingOccupancyFraction:调整触发CMS的百分比。
- 空间碎片处理:-XX:UseCMSCompactAtFullCollection,用于在碎片太多以至于不得不Full GC的时候进行一次碎片整理。-XX:CMSFullGCsBeforeCompaction:设置执行多少次Full GC后执行一次碎片整理。
G1(garbage first)