持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情
5 垃圾回收与算法
5.1 如何确定垃圾
Java采用引用计数法和可达性分析来确定对象是否应该被回收。
(1)引用计数法
在Java中如果要操作对象,就必须先获取该对象的引用,因此可以通过引用计数法来判断一个对象是否可以被回收。
在为对象添加一个引用时,引用计数加 1;在为对象删除一个引用时,引进计数减 1;如果一个对象的引用计数为 0,则表示此刻该对象没有被引用,可以被回收。
引用计数法容易产生循环引用问题。循环引用指两个对象相互引用,导致它们的引用一直存在,而不能被回收
(2)可达性分析
为了解决引用计数法的循环引用问题,Java还采用了可达性分析来判断对象是否可以被回收。
-
不可达
- 首先定义一些GC Roots对象,然后以这些GC Roots对象作为起点向下搜索,如果在GC roots和一个对象之间没有可达路径,则称该对象是不可达的。
-
两次标记
- 不可达对象要经过至少两次标记才能判定其是否可以被回收,如果在两次标记后该对象仍然是不可达的,则将被垃圾收集器回收。
5.2 Java中常用的4种垃圾回收算法
(1)标记清除算法(快、但是存在碎片)
(2)复制算法(无碎片、但要占用双倍内存空间)⭐️
(3)标记整理算法(慢、无碎片)⭐️
(4)分代收集算法
- 对象首先分配在伊甸园区域
- 新生代空间不足时,触发 minor gc,伊甸园和 from 存活的对象使用 copy 复制到 to 中,存活的对象年龄加 1并且交换 from to
- minor gc 会引发 stop the world,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行
- 当对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4bit)
- 当老年代空间不足,会先尝试触发 minor gc,如果之后空间仍不足,那么触发 full gc,STW的时间更长
6 Java中的4种引用类型
在Java中一切皆对象,对象的操作是通过该对象的引用(Reference)实现的。
Java中的引用类型有4种,分别为强引用、软引用、弱引用和虚引用。
强(最常见)
在把一个对象赋给一个引用变量时,这个引用变量就是一个强引用。
有强引用的对象一定为可达性状态,所以不会被垃圾回收机制回收。
因此,强引用是造成Java内存泄漏(Memory Link)的主要原因。
软(通过SoftReference类实现)
如果一个对象只有软引用,则在系统内存空间不足时该对象将被回收。
弱(通过WeakReference类实现)
如果一个对象只有弱引用,则在垃圾回收过程中一定会被回收。
虚(通过PhantomReference类实现)
虚引用和引用队列联合使用,主要用于跟踪对象的垃圾回收状态。