GC基础总结

一、概述

数据区 是否共享 回收方案
程序计数器 X 同线程或方法消亡回收
虚拟机栈 X 同线程或方法消亡回收
本地方法栈 X 同线程或方法消亡回收
方法区 GC处理
GC处理

因为线程不共享的区域其数据回收可以根据方法乃至整个线程的结束来决定,所以GC要处理的对象是方法区与堆。
二、如何判断堆中的对象废弃

算法 alias 使用语言 优势 劣势
引用计数法 reference counting Python 原理简单,效率高,只要记录被引用次数即可 互相循环引用的情况难以判定
可达性分析法 reachability analysis JAVA/C# 通过GC ROOTS可以清晰知道谁在被有效使用 效率低

JAVA使用的是可达性分析法。可达性分析法中的GC Roots设置至关重要。目前包括以下几种:
1.虚拟机栈的本地变量表中所引用的对象,对应在程序中可为各线程所使用的参数、局部变量、临时变量等。
2.本地方法栈中的JNI引用的对象。
3.所有被synchronized持有的对象。
4.方法区中常量所引用的对象,比如字符串常量池(String Table)里面的引用。
5.方法区中静态属性所引用的对象,比如Java类的引用型静态变量。
6.JAVA虚拟机自己的内部引用,如基本数据类型对应的Class对象,一些常驻的异常,以及系统加载器。
7.反应Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。
8.还有一些特殊的对象可能临时性加入。比如分代收集、局部回收等。
三、引用
JDK1.2前定义:如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,就称其是某块内存、某个对象的引用。
JDK1.2后扩充:引用分为强引用、软引用、弱引用、虚引用。只有强引用不会被回收,其他引用都不安全。
四、挽留
GC发现存在不可达的对象时并不会马上击毙对象,在此之前,GC会先问问这个对象有什么遗嘱,该对象没遗嘱就当场击毙,如果有遗嘱(覆盖finalize()方法),就安排它去办手续排队处理(F-Queue)。
死刑犯在办手续时,可以去托人找关系,如果抱上了大腿(GC Roots)则可以免去一死,如果只是废话连篇,那就在执行完遗嘱后原地去世。
但是要注意的是,总有极个别死刑犯的遗嘱比较奇葩,以至于影响到GC去实现后面死刑犯的遗嘱。不得已,GC只能不负责任地执行它们的遗嘱,但是却不等候执行结果。由此可见,使用遗嘱方法(finalize)是不靠谱的。在程序中应避免使用此函数。

猜你喜欢

转载自blog.csdn.net/weixin_44159662/article/details/107755849