那些内存需要回收?
Java堆和方法区(废弃常量,无用的类)
废弃的常量:没有任何引用指向常量池中的常量,也没有使用字面量。
无用的类(类卸载):我们知道,class文件内存加载的时候,会加载到方法区(或元空间)。
如果该类的所有对象实例都被回收了,并且加载此类的ClassLoader也被了。
最重要的java.lang.Class对象没有了引用,并且也没有通过反射访问。
类就可以卸载出内存了。
什么时候回收?
用可达算法判断两次标记后
如何回收?
需要根据jvm垃圾收集器算法回收。
jvm垃圾收集器的回收算法种类
一、标记-清除算法(Mark-Sweep)
标记-清除算法是最基础收集算法。(适合回收老年代)。
工作分为两个阶段:
1.标记
2.清除
不足之处:1.效率不稳定,如果包含大量回收对象那么标记和清除过程执行效率都会降低。
2.标记清除后会产生大量内存碎片。
二、复制算法
这种代价将内存缩减了一半(适合回收新生代),运行高效。
工作分为两个阶段:
1.标记
2.将活着的对象方式另一块区域
3.清除
三、标记-整理算法
这种算法效率低(适合回收老年代),为什么会低?
工作分为两个阶段:
1.标记
2.清除
3.整理
四、分代收集算法
把Java堆分为新生代和老年代根据不同年代选择算法。
例如:在新生代中,每次都会收集大量对象,所以可以选择复制算法,只需要付出少量对象的 复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们选择“标记-清除”或“标记-整理”算法进行垃圾收集。