java GC
资料:
GC Roots、分代(R大):https://www.zhihu.com/question/53613423
0. 引用分类
1. 强引用
2. 软引用
3. 弱引用
4. 虚引用
1. GC Roots
1. 虚拟机栈(栈帧中本地变量表)中的引用
2. 本地方法栈 JNI (Native 方法) 的引用
3. 方法区中类静态属性的引用
4. 方法区中常量的引用
引用:*obj 在栈中,保存obj对象的地址
对象:object 在堆中
2. 可达性分析
标记活着的对象
通过GC Roots作为起点,向下搜索引用链。当一个对象到 GC Roots 没有引用链相连时,说明可回收。
实现:枚举根节点
1. stop the world
保证引用不会变化,CMS在枚举根节点时也会停顿
3. 回收对象(谁会被GC)
从root搜索不到,而且经过第一次标记、清理后(finalize方法),仍然没有复活的对象。
标记分为两步:
1. 是否需要调用finalize方法
2. 调用finalize方法之后是否存活
4. GC 触发条件(什么时候GC)
Minor GC / young GC:
1. eden区满
Old GC:
1. CMS定期检查Old Gen使用量,超过了触发比例启动CMS GC,对Old Gen做并发收集。
Full GC:
1. 升到老年代的对象大于老年代剩余空间full gc
2. 有Perm Gen的话,要在Perm Gen分配空间但是没有足够空间
5. 分代的好处
1. 对串行:若无分代,一次GC整个堆(对传统的serial来说),stop the world 停顿时间太长,不如一次只收集一部分,减少停顿时间,young gen需要收集的次数多,old gen需要次数少。
// 未理解:2. 对并行:提升GC能够应付的应用内存分配速率
6. 谁会进入老年代
1. 大对象直接进入老年代(高于阈值)
2. 长期存活的对象进入老年代
熬过15次Minor GC
3. 动态对象年龄判定
Survivor中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于等于该年龄的对象直接进入老年代
4. 老年代分配担保
Minor GC后大量对象存活,Survivor无法容纳的对象进入老年代
7. 方法区回收
对象:废弃常量、无用的类
1. 废弃常量
常量池中的 字面量、类、方法、字段的符号引用
例:"abc"在常量池中,但没有任何一个String对象是"abc",也没有其他地方引用了这个字面量。
2. 无用的类 (可能被回收)
1. 该类所有实例被回收
2. 加载该类的ClassLoader被回收
3. 该类Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类方法
3. 元空间的垃圾回收
资料:https://www.cnblogs.com/duanxz/p/3520829.html
1. 在元空间中,类和其元数据的生命周期和其对应的类加载器是相同的。
2. 每一个类加载器的存储区域都称作一个元空间,所有的元空间合在一起就是我们一直说的元空间。当一个类加载器被垃圾回收器标记为不再存活,其对应的元空间会被回收。
3. 元空间虚拟机负责元空间的分配,其采用的形式为组块分配。组块的大小因类加载器的类型而异。在元空间虚拟机中存在一个全局的空闲组块列表。当一个类加载器需要组块时,它就会从这个全局的组块列表中获取并维持一个自己的组块列表。当一个类加载器不再存活,那么其持有的组块将会被释放,并返回给全局组块列表。类加载器持有的组块又会被分成多个块,每一个块存储一个单元的元信息。组块中的块是线性分配(指针碰撞分配形式)。组块分配自内存映射区域。这些全局的虚拟内存映射区域以链表形式连接,一旦某个虚拟内存映射区域清空,这部分内存就会返回给操作系统。
8. 复制算法
资料: