GC过程

总体来说要判断:

哪些内存需要回收?——who
什么时候回收?——when
怎么回收?——how

1、哪些内存需要回收?

在这里插入图片描述

2、什么时候回收?

(1)、引用计数法

Object a = new Object(); // a的引用计数为1
a = null; // a的引用计数为0,等待GC回收

但是,引用计数法不能解决对象之间的循环引用,见下例

Object a = new Object(); // a的引用计数为1
Object b = new Object(); // b的引用计数为1

a.next = b; // a的引用计数为2
b.next = a; // b的引用计数为2

a = null; // a的引用计数为1,尽管已经显示地将a赋值为null,但是由于引用计数为1,GC无法回收a
b = null; // b的引用计数为1,同理,GC也不回收b

(2)、可达性分析

设立若干根对象(GC Root),每个对象都是一个子节点,当一个对象找不到根时,就认为该对象不可达。
在这里插入图片描述
java中,可以作为GC Roots的对象包括:
java虚拟机栈中引用的对象
方法区中静态变量引用的对象
方法区中常量引用的对象
本地方法栈中引用的对象

3、怎么回收?

标记——清除算法
复制算法
分代算法

(1)、标记——清除算法

遍历所有的GC Root,分别标记处可达的对象和不可达的对象,然后将不可达的对象回收。

缺点是:效率低、回收得到的空间不连续

(2)、复制算法

将内存分为两块,每次只使用一块。当这一块内存满了,就将还存活的对象复制到另一块上,并且严格按照内存地址排列,然后把已使用的那块内存统一回收。

优点是:能够得到连续的内存空间
缺点是:浪费了一半内存

在这里插入图片描述
(3)、分代算法(Generational recycling)
在java中,把内存中的对象按生命长短分为:

新生代:活不了多久就go die 了,比如局部变量
老年代:老不死的,活的久但也会go die,比如一些生命周期长的对象
永久代:千年王八万年龟,不死,比如加载的class信息

新生代和老年代存储在java虚拟机堆上 ;永久代存储在方法区上

在这里插入图片描述
摘自:https://blog.csdn.net/u010429424/article/details/77333311

猜你喜欢

转载自blog.csdn.net/NIUBILISI/article/details/90030811