在 JVM 进行垃圾回收之前,首先就是判断哪些对象是垃圾,也就是说,要判断哪些对象是可以被销毁的,其占有的空间是可以被回收的。
根据 JVM 的架构划分,我们知道在 Java 中,几乎所有的对象实例都在堆中存放,所以垃圾回收也主要是针对堆来进行的。
在 JVM 的眼中,垃圾就是指那些在堆中存在的,已经“死亡”的对象。我们可以理解为 “不可能再被任何途径使用的对象”。那如何判断对象的存活和死亡呢?这就涉及到了垃圾判断算法,其主要包括引用计数法和可达性分析法。
在这种算法中,假设堆中每个对象中都有一个引用计数器。

当一个对象被创建并且初始化赋值后,该对象的计数器 ref_count = 1,每当有一个地方引用它时,ref_count ++。例如将对象 b 赋值给对象 a,那么 b 被引用,则将 b 引用对象的计数器累加 1。
Person p1 = new Person(18); // ref_count = 1;
Person p2 = p1; // ref_count ++ = 2;
method(p1);
void method(Person s) { // ref_count ++ = 3;
} // ref_count -- = 2;
反之,当引用失效时,例如一个对象的某个引用超过了生命周期(出作用域后)或者被设置为一个新值时,则ref_count --。
当一个对象的 ref_count = 0 时,就可以称之为垃圾,可以被回收。
// 当 原来的引用 指向一个新对象时
p1 = new Person(20); // ref_count -- = 1;
p2 = null; // ref_count -- = 0;
// 原来的 Person(18) 被回收
当一个对象死亡,对象中的引用失效,导致该引用指向的对象的ref_ count–,可能引起其它对象(它内部引用的)继续死亡。
优点:引用计数法实现起来比较简单,对程序不被长时间打断的实时环境比较有利。
缺点:需要额外的空间来存储计数器,难以检测出对象之间的循环引用。
目前主流的JVM中使用的是另一种方式 : 可达性分析法。

Java 应用是没有资格直接访问对象,只能通过引用简介的访问对象。
我们现在已经找到了垃圾对象了,所以探讨如何进行垃圾回收(内存空间的回收)。
我们站在内存管理器 GC 的角度,把自己看出一个房东,有很多房间。
分配内存(把房子租出去)。
回收内存(收回房子,只需要作状态变更:已被出租->空闲状态)。
整理内存打扫房间 (把空间中数据清空)。当下次需要该房间时才会去打扫房间,或者 定期将所有房间重新整理,防止内存碎片化。

分代收集(Generational Collector)算法就是其中一种针对GC性能优化算法,将堆内存划分为新生代、老年代。

对象的生命周期:每经历一次GC,对象年龄 + 1。

伊甸区:是对象诞生的地方。经过经验的推算,大部分对象的生命基本活不过1岁。
生存区:活过了1岁,但大部分也活不到成年15岁。这些对象每经历一次 GC,会在 SA 和 SB 之间反复横跳。
老年区:极少数成年的对象 或者 大对象会被一开始放在这儿。
对象的一生:
GC被分为三种:
Minor GC) 。Major GC) 。Full GC)。在分代收集算法中,对象的存储具有以下特点:
总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是JVM的学习,了解了JVM垃圾回收机制的原理,以及分代收集的GC算法。之后的学习内容将持续更新!!!