一、怎么判断一个对象为垃圾
1.在我们的jvm中有一个root根节点。root根节点会引用对象,如果一个对象做可达性分析能够到root根节点,则表示该对象不是垃圾(1,2,3,4),但是如5.6两个对象虽然两者间有相互引用,但是到root根节点不可达,则表示为垃圾,将会被垃圾收集器回收。
2.哪些是root根节点。
类加载器、Thread、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈变量等,这些都是root根节点,因为这些在程序运行过程中,怎么都不会被垃圾收集器回收,而其他对象是否是垃圾则对这些做可达性分析。
二、常用算法
1.标记清除
该算法分为两个阶段“标记”、“清除”。第一次先标记出哪些是垃圾,第二次将标记的对象进行清除(销毁)。
缺点:效率不高、标记和清除两个过程效率都不高
产生空间碎片,因为被标记的对象在空间物理上并不一定是连续的,当清除完之后,我们剩下存活的对象在物理上也不一定是连续的,这就意味着这些不连续的对象之间有很大一部分空间将利用不到,则是空间碎片。
2.复制算法
首先将内存分为大小相等的两块,每次只使用其中的一块,当第一块中的内存用完时,做可达性分析,将存活的对象复制到另一块去,然后对第一块内存做一次全部清理。
优点:效率高,不会产生空间碎片
缺点:空间利用率不高。只有50%。
3.标记整理
和标记清除算法类似,但是在第一阶段标记之后,并不是自己进行清除,而是将存活的对象移至空间的一段,然后对端边界以外的内存直接进行一次清理
优点:不会产生空间碎片
缺点:标记整理效率不高,很耗时。
三、jvm使用
1.算法使用
jvm中young区使用的是复制算法,因为在young区一般对象存活的时间不长,产生垃圾的速度比较快,所以采用效率较高的算法。
old区主要使用标记清除或标记整理,因为一般在old区的对象存活时间比较长,不需要经常做垃圾回收,所以采用效率不高,但空间利用较高的算法
四、对象分配
1.对象优先在Eden区分配。
2.如果是大对象,可以直接进入老年代。什么才是大对象。-XX:PretenureSizeThreshold 超过这个参数的值则表示为大对象。
3.长期存活的对象进入老年代,什么才是长期存活的对象。
-XX:MaxTenuringThreshold 经历了这个参数值的minor gc之后可进入老年代
-XX:+PrintTenuringDistribution 输出在Survivor区对象的年龄情况,相当于日志
-XX:TargetSurvivorRatio 通过一个公式计算sutvivor区的对象是需要进入old区。