一,概述
1, 从java内存区域说起
java内存区域通常划分为这么几块:
(1) java堆: 对象及数组引用
(2) 虚拟机栈: 局部变量等
(3) 方法区: 类相关信息,常量、静态变量等
(4) 程序计数器
(5) 本地方法栈
其中,程序计数器和虚拟机栈是线程私有的,随着线程的创建而创建,随着线程的销毁而销毁。
java堆和方法区,则是所有线程共享的区域。
2, 一提到java,我们都会提到一个概念GC-垃圾回收,都说jvm会帮我们自动的进行垃圾回收,那么,问题来了:
(1), 回收什么?
(2), 什么时候回收?
(3), 怎么回收?
带着这三个问题,我们来研究一下jvm的GC机制。
二,回收什么?
简单的说,是回收对象。那么是那些对象会被回收呢?
答案是,那些“死亡”的对象。
那么,怎么判断一个对象是“死亡”的呢?
1, 引用计数算法
每个对象添加一个引用计数器,每当有一个地方引用它时,引用计数器+1, 当引用失效时,计数器-1,所以,任何时刻计数器为0的对象,就是不可被引用的对象,即是“死亡”的。
该算法存在一个缺陷,不能解决对象循环引用的问题
2, 可达性分析算法
通过一些列的别成为“GC Root”的对象作为起点,向下搜索,搜索走过的路径被称为“引用链”,当一个对象到任何一个GC root没有引用链,则该对象不可用。
在java中,可作为GC root的对象有:
* 虚拟机栈中引用的对象
* 方法区中类静态属性引用的对象
* 方法区中常量引用的对象
三, 什么时候回收
这要从对象的内存分配说起。
对象创建,会在前面说到的堆上分配空间。堆内存往细划分,有新生代和老年代,新生代有划分为Eden、Survivor, 其中Survivor又包含from survivor和to survivor。
在大多数情况下,对象优先在Eden区中分配,当Eden区中没有足够的空间分配时,虚拟机将发起一次Minor GC。
如果对象出生在Eden区,并且经过第一次Minor GC后仍然存活,并且能被Survivor接纳,那么该对象将被Survivor空间中。
四,怎么回收
常用的回收算法有很多,例如
1, 标记-清除
2, 复制
3, 标记-整理
4, 分代收集算法