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收集器
一、首先,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收集器
相关文章推荐
- java中stack 和 heap的区别,java中的垃圾回收机制
- JavaGC(1)—深入浅出Java垃圾回收机制
- Java 垃圾回收机制
- Java Garbage Collection基础详解------Java 垃圾回收机制技术详解
- Java的垃圾回收机制
- java 垃圾回收机制
- java垃圾回收机制
- Java程序设计(三)垃圾回收机制
- Java千百问_07JVM架构(008)_java垃圾回收机制是什么
- Java垃圾回收机制
- Java 垃圾回收机制
- Java垃圾回收机制
- Java垃圾回收机制
- Java垃圾回收机制
- java垃圾回收机制
- 深刻剖析经典面试题之二:Java与C#的垃圾回收机制
- JAVA内存回收(1)—深入浅出Java垃圾回收机制
- 浅析JAVA之垃圾回收机制
- java垃圾回收机制中的算法
- JAVA垃圾回收机制与内存泄露问题