垃圾收集算法包括:Mark-Sweep算法、Copying算法、Mark-Compact算法。
概述:HotSpot是按照分年代进行回收Generational Collection。分为新生代、老年代、永久代
前言
根据对象的生命周期的不同,将内存划分为几块,一般把Java堆分为新生代和老年代,把方法区划分为永久代。
在新生代中,每次垃圾回收都有大量的对象死去,只有少量的对象存活,所以只需额外较小的空间来存储这些存活的对象,适用于复制算法。
老年代对象存活率高,每次回收都有大量的对象存活,没有额外的空间进行分配担保,所以一般使用标记-清除,标记-整理算法进行回收。
永久代在HotSpot是否收集可以通过参数进行设置,但是收集性价比低,没有对新生代的回收来的实惠(释放大量的空间)。
Copying(复制算法HotSpot的实现)
为了解决Mark-Sweep算法的效率问题
- 将内存空间划分为一块较大的空间Eden和两块Survivor,比例为8:1:1。记为E、S1、S2
- 每次使用Eden和其中一块Survivor,记为E、S1。当进行垃圾回收时,将E、S1的存活的对象复制到S2上,然后直接清除掉S1,并对E用过的区域进行清理;下次新生代分配对象会分配在E上。如果S2上的内存空间不够存储上一次垃圾收集新生代存活的对象(E、S1上)会向老年代内存空间上进行分配担保(借一些空间来存储,然后保证使用完后还回去)
- 特点:分配效率高,清除后的空间是连续的。在HotSpot中常用来对新生代进行回收
Mark-Sweep(标记-清除算法)
- 顾名思义,算法分为两步:标记出所有需要回收的对象,标记完成后统一进行回收。
- 缺点:这是最基本的垃圾收集算法
- 标记和清除阶段的效率都不高。
- 标记清除后将会产生大量不连续的空间,导致想要分配大对象时,还需在进行一次垃圾回收。
Mark-Compact(标记-整理算法)
- 标记存活的对象,然后将标记的对象向一端移动,这样存活的对象就都聚到一起了,然后就可以清除存活边界以外的内存空间了。
- 得到规整连续的空闲空间,分配新对象效率高,专门对老年代对象进行回收
永久代中的垃圾收集
方法区哪些对象需要进行回收?
无用的常量和类
常量
- 字面量:"hhhhh”等不是通过new创建的字符串(其实这一部分称为 String Constant Pool),final int等一些基本数据类型常量。
- 类(接口)、方法、字段等的符号引用
无用的类(Class对象)
满足下面三个条件的类对象才会被回收(HotSpot中必须设置对应的参数,使能对永久代的回收)
- 该类的所有实例对象已被回收,即Java堆中不存在此类的实例
- 加载该类的ClassLoader已经被回收
- 该类对应的java.lang.Class对象没有在任何地方被引用,即无法再通过反射类访问这个类的方法。