原始数据类型存储到栈,引用类型存储到堆
f1 -> f2
将f2的上下文推入栈中
等f2执行完后,f2的上下文变为废弃状态,类似于硬盘删除文件,这就是原始数据类型的垃圾回收
标记回收
f2的栈里面有一个obj2堆,当f2运行结束后回到f1,查找f1的运行栈,没有obj2,标记obj2需要回收
代际假说
根据代际假说,内存被分为不同的代(generations),通常分为年轻代(young generation)和老年代(old generation)两个部分。这种分代的策略基于以下观察: 年轻代(Young Generation): 在程序运行的初期,大部分对象都是临时的,它们被创建后不久就会变得不再可达(被垃圾回收)。 因此,年轻代包含了大量的临时对象,这些对象经历了多次的垃圾回收。 年轻代通常被划分为三个部分:Eden区、From区和To区。新创建的对象在Eden区分配,经过一次垃圾回收后,仍然存活的对象会被移动到From区,然后在下一次垃圾回收时,存活的对象从From区复制到To区。这个过程不断重复,直到对象变得足够老,就会被晋升到老年代。 老年代(Old Generation): 对象在经历多次年轻代的垃圾回收后,如果仍然存活,它们就会被晋升到老年代。 老年代通常包含生存周期更长的对象,因此垃圾回收发生得较少,且代价更高。 代际假说的基本思想是将垃圾回收集中在年轻代,因为大部分对象很快就会被回收,从而减少了垃圾回收的成本。只有那些经历了多次回收的对象才会被提升到老年代
新生代垃圾回收
新生区域只有1~8MB
将区域分为运行区域,空闲区域
运行区域满了,就会执行一次gc
将标记存活的对象拷贝到空闲区域,并碎片化整理
然后两个区域翻转
如果对象连续两次还存活,会进入老生区
老生区垃圾回收
如果对象太大,或者存活时间较长,对象会进入老生区
老生区采用标记回收进行gc
三色标记
gc的首要保证是不能删除存活的节点,然后才是回收没有用到的节点
为了能够在空闲时时候gc,需要有个中间状态知道gc到那个地步了
黑色代表gc已经处理过的节点,灰色代表将要处理的节点,白色代表还未处理的节点
当gc中断后恢复,就从灰色继续处理
为了防止两次cg之间,节点的指向发生改变导致遍历不到存活的节点
因此,黑色后面不能跟白色,白色只能跟在灰色后面