您的位置:首页 > 编程语言 > Java开发

Java垃圾回收机制

2018-01-31 21:18 197 查看
JVM垃圾回收不是必须的,只有在堆空间不足的时候回收。

一、首先,JVM判断对象是否存活,有两种方法

1、引用计数法

对象每被引用一次,加1。如果引用次数为零,判断对象不可再使用。会有循环引用问题

2、可达性分析法

通过一系列GC Roots对象作为起点,从这些起点开始找它的引用,它的引用的引用。如果某个对象到达不了,说明该对象不可用。

GC Roots对象可以有:

1、虚拟机栈中引用的对象。

2、方法去中类的静态属性引用的对象

3、方法区中常量引用对象

4、本地方法栈中引用的对象

二、筛选出不可达对象后,对象也不是非死不可,进行如下工作

1、第一次标记

看这些对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法或则finalize()方法被调用过后,虚拟机将这两种情况视为没有必要执行,可以回收。

2、第二次标记

如果判断对象有必要执行finalize()方法,那么这个对象会放置在F-Queue队列中,稍后会重新进行一次标记,执行finalize()方法,这时候只要对象在finalize()方法中拯救自己,比如把自己(this关键字)复制给某个类变量或者对象的成员变量,就可以避免被回收。如果还是没有逃脱,那基本上是被回收了。

三、垃圾回收算法

1、标记-清除算法

标记所有要回收的对象,清除对象。产生如下两样问题

效率不高,到了垃圾回收阶段了,要回收的对象是比不回收的要多的,遍历所有的要回收的对象,一一清除内存地址上的内容。

会产生大量不连续的内存。如果要分配大对象,无法找到足够的连续内存不得不提前触发另一次垃圾回收动作。

2、复制算法

划分两块大小相等的内存,每次只使用其中一块,这块用完了,将还活着的对象复制到另外一块,再把使用过的内存空间一次清理掉。存在的问题是只能用一块内存了。

优化的方法是,不需要1比1划分空间。因为很多对象的生命周期很短,要回收的对象是远远大于需要保留的对象,所以开辟8:1:1的内存,称作Eden和survivor,每次使用Eden和其中一块survivor空间,利用率达到90%,要回收了,把保留的对象转移到另一块survivor内存上。如果10%空间不够,需要依赖其他内存进行担保。

对象在Eden出生并经过第一次monitor GC后进入survivor,设置对象年龄为1。在survivor中每熬过一次minor GC,年龄就加1岁,当年龄加到一定程度,默认15岁时,进入老年代。

3、标记-整理算法

把保留的对象向内存的一边挪,然后直接清理掉端边界以外的内存。

新生代采用复制算法收集内存。老年代 标记-清除算法和标记-整理算法。

四、收集器

1、serial收集器 新生代 单线程 复制算法

2、serial Old收集器 老年代 标记-整理算法

3、pawNew收集器 serial收集器的多线程版本

4、parallel Scavenga收集器 新生代收集器,复制算法,关注程序吞吐量

5、parallel Old收集器的老年代版本 标记整理算法

6、CMS收集器 获取最短回收停顿时间为目标的收集器

7、G1收集器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: