如何判断对象是否存活/死去
在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器对堆内存进行回收前,都会先判断这些
对象之中哪些还“存活”着,哪些已经“死去”(即不可能在被任何途径使用的对象)。一共有两种算法:
1、引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器
值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
JVM里面并没有选用引用计数算法来管理内存,主要原因是它很难解决对象之间相互循环引用的问题。
2、可达性分析算法
通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为
引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
如何判断一个常量是废弃常量
运行时常量池主要回收的是废弃的常量。
假如在常量池中存在字符串“abc”,如果当前没有任何String对象引用该字符串常量的话,就说明常量“abc”就是废弃常量,如果这时发生内存回收而且有必要的话,“abc”就会被系统清理出常量池。
如何判断一个类是无用的类
方法区主要回收的是无用的类;
判定一个常量是否是“废弃常量”比较简单,而要判定一个类是否是“无用的类”的条件则相对苛刻许多。
类需要同时满足下面3个条件才能算是“无用的类”:
JVM可以对满足上述3个条件的无用类进行回收,仅仅是“可以”,而并不是和对象一样不使用了就必然会被回收。
垃圾收集算法
1、标记-清除算法
算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它是最基础的收集算法,但是会带来两个明显的问题:
(1)效率问题
(2)空间问题(标记清除后会产生大量不连续的碎片)
2、复制算法
为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。(比较适合内存相对较小的Survivor区中的From和To)
3、标记-整理算法
根据老年代的特点推出的一种标记算法,标记过程仍然与“标记-清除“算法一样,但后续步骤不是直接对可回收对象进行回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
4、分代收集算法
当前JVM的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将Java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。
G1垃圾收集分类:
Young GC:
Mixed GC:
Minor Gc和Full GC 有什么不同呢
HotSpot为什么要分为新生代和老年代
原文:https://www.cnblogs.com/songyuejie/p/12549689.html