前置知识:
之前在对象的内存布局中,提到对象头 mark word有个分代年龄。下面总结一下垃圾收集算法。
哪些内存需要回收:
垃圾收集主要是针对堆内存区域中的对象的垃圾收集,因为程序计数器 虚拟机栈 本地方法栈3个区域的声明周期是依赖线程的。方法或者线程结束,内存就自然回收了。方法区(永久代)也可能会回收但是条件会很苛刻。但是大量使用反射 动态代理以及相关框架,osgi这种大量定义classloader的场景需要虚拟机具备类的卸载功能,以保证永久代不会溢出。
垃圾收集算法有引用计数算法和可达性分析算法,主流的虚拟机都是通过后者来判断对象是否存活。可达性分析算法是被称作GC root的对象作为起始点,当一个对象的GC root没有任何引用链的话就会被回收。
GC root的对象包括:
本地变量表引用的对象,方法区静态属性和常量引用的对象,本地方法栈jni或者说native方法引用的对象。
垃圾收集算法:
标记-清除算法,缺点是碎片多,分配大对象可能回重新启动垃圾回收。复制算法,主要用于回收新生代,内存被分为eden空间和surviver空间,这种分配方式,空间浪费只有百分之10,当survivor空间不够用时,会通过分配担保机制进入老年代。
标记-整理算法,适用于老年代,所有存活的对象都移动向一端,然后清理掉边界以外的内存。
商用垃圾收集器:
serial -- parnew 多线程版本。---老年代配合serial old cms。parallel scavenge 。吞吐量优先 精确控制停顿时间但是会减小吞吐量 增加频率。也能精确控制吞吐量 通过时间比。也有自适应调节策略。不用在自己分配新生代各个区域 晋升老年代对象大小 等等参数。
parallel scavenge 不能与 cms。 可以与serial old 但是出了parallel old 两者就完美组合了。
cms 老年代收集器。 以获取最短回收停顿时间为目标。
g1 garbage-first
分代收集算法,就是根据各个代的特点来选用合适的回收算法。