java面试之GC(垃圾收集器)
2016-03-25 13:13
375 查看
GC:
gc不仅负责垃圾回收,还决定内存分配。
java内存管理主要是对内存中的对象进行内存的分配和回收,我们都知道当我们创建一个对象时,对象的引用放在栈(Stack)中,对象放在堆(heap)中,gc只回收堆里面的对象。当gc检测到一个堆中的一个对象不在被引用时,就会对这个对象进行回收。
当我们创建一个对象时,gc就会监视这个对象的地址,大小以及状态。gc有特定的回收算法,通常使用有向图来记录管理堆中的对象,通过这种方式来确定那些对象正在被引用,那些已经不在被引用,当一个对象不在被引用时,gc就有权回收这个对象。当然可以使用System.gc();Runtime.getRuntime().gc();来显示调用gc。但是java规范不保证gc不一定立即回收。
gc可以使我们在开发时候不用考虑内存回收的事情了,可以防止内存泄漏。
垃圾收集的实现种类:
1. 引用计数:
一个A对象,如果有程序使用了这个引用对象,那么引用计数加1,当一个对象使用完毕之后引用计数减1,那么引用计数为0的时候,则可以回收。
他不能识别循环引用
2. 跟踪收集:
root set :当前正在执行的线程;全局或者静态变量;JVM Handles;JNDI Handles
从root set 开始扫描有引用的对象,如果某个对象不可以到达,则说明这个对象已经dead,GC可以对其回收。也就是说:如果A对象引用了B对象,那么虚拟机会记住这个引用路径,同时B对象引用了C对象,那么也会记录这个路径如果一个对象没有在路径图中,那么可以收集。
需要维护一张引用的全景图,增加了内存开销,和图的遍历开销。
3. 基于对象跟踪的分代增量收集 :
基于对象跟踪:说明是由跟踪收集发展而来的,分代是指对堆进行了合理的划分,
增量收集:不是每一次全部收集,而是累积的增量收集。
Sun的JVM将整个堆分为三代:YoungGen(新生代),OldGen(年老代),和PermGen(持久区):
Minor GC:通常是指对新生代的回收。
Major GC:通常是指对年老代的回收。
Full GC:Major GC除并发gc外均需对整个堆进行扫描和回收。
复制拷贝算法:要拷贝大量数据,不会产生碎片。
标记算法:从引用根节点开始标记所有被引用的对象,把未被引用的对象清除。要遍历所有对象,会产生碎片。
young
又分为eden,survivor1(from space ),survivor2(to sapce ).youngGen区里面的对象的生命周期比较短,gc对这些对象进行回收的时候采用复制拷贝算法。
eden 每当一个对象创建的时候分配的这个区域。当eden无法分配时,触发一次Minor gc。gc每次回收的时候都将eden区存活的对象和survivor1中的对象拷贝到survivor2中,eden和survivor1清空;当gc执行下次回收的时候将eden和survivor2中的对象拷贝到surivor1中,清空eden和survivor2。依次这样执行;经过数次回收将依然存活的对象复制到OldGen区。
OldGen 当对象从年轻代晋升到老年代之前,会检测老年区的剩余空间是否大于要晋升对象的大小,如果小于则直接进行一次Full GC,以便让老年去腾出更多的空间,然后再进行Minor GC,把年轻代的对象复制到老年代;如果大于,则根据条件(HandlePromotionFailure设置)进行Minor GC 和 Full GC。
老年区采用标记算法,因为老年区对象的生命周期都是比较长的,采用拷贝算法要拷贝大量的数据。采用标记算法每次gc回收都要遍历所有的对象。
PermGen 主要存放加载进来的类信息,包括方法,属性,常量池等,满了之后可能会引起out of memory 错误。
gc不仅负责垃圾回收,还决定内存分配。
java内存管理主要是对内存中的对象进行内存的分配和回收,我们都知道当我们创建一个对象时,对象的引用放在栈(Stack)中,对象放在堆(heap)中,gc只回收堆里面的对象。当gc检测到一个堆中的一个对象不在被引用时,就会对这个对象进行回收。
当我们创建一个对象时,gc就会监视这个对象的地址,大小以及状态。gc有特定的回收算法,通常使用有向图来记录管理堆中的对象,通过这种方式来确定那些对象正在被引用,那些已经不在被引用,当一个对象不在被引用时,gc就有权回收这个对象。当然可以使用System.gc();Runtime.getRuntime().gc();来显示调用gc。但是java规范不保证gc不一定立即回收。
gc可以使我们在开发时候不用考虑内存回收的事情了,可以防止内存泄漏。
垃圾收集的实现种类:
1. 引用计数:
一个A对象,如果有程序使用了这个引用对象,那么引用计数加1,当一个对象使用完毕之后引用计数减1,那么引用计数为0的时候,则可以回收。
他不能识别循环引用
2. 跟踪收集:
root set :当前正在执行的线程;全局或者静态变量;JVM Handles;JNDI Handles
从root set 开始扫描有引用的对象,如果某个对象不可以到达,则说明这个对象已经dead,GC可以对其回收。也就是说:如果A对象引用了B对象,那么虚拟机会记住这个引用路径,同时B对象引用了C对象,那么也会记录这个路径如果一个对象没有在路径图中,那么可以收集。
需要维护一张引用的全景图,增加了内存开销,和图的遍历开销。
3. 基于对象跟踪的分代增量收集 :
基于对象跟踪:说明是由跟踪收集发展而来的,分代是指对堆进行了合理的划分,
增量收集:不是每一次全部收集,而是累积的增量收集。
Sun的JVM将整个堆分为三代:YoungGen(新生代),OldGen(年老代),和PermGen(持久区):
Minor GC:通常是指对新生代的回收。
Major GC:通常是指对年老代的回收。
Full GC:Major GC除并发gc外均需对整个堆进行扫描和回收。
复制拷贝算法:要拷贝大量数据,不会产生碎片。
标记算法:从引用根节点开始标记所有被引用的对象,把未被引用的对象清除。要遍历所有对象,会产生碎片。
young
又分为eden,survivor1(from space ),survivor2(to sapce ).youngGen区里面的对象的生命周期比较短,gc对这些对象进行回收的时候采用复制拷贝算法。
eden 每当一个对象创建的时候分配的这个区域。当eden无法分配时,触发一次Minor gc。gc每次回收的时候都将eden区存活的对象和survivor1中的对象拷贝到survivor2中,eden和survivor1清空;当gc执行下次回收的时候将eden和survivor2中的对象拷贝到surivor1中,清空eden和survivor2。依次这样执行;经过数次回收将依然存活的对象复制到OldGen区。
OldGen 当对象从年轻代晋升到老年代之前,会检测老年区的剩余空间是否大于要晋升对象的大小,如果小于则直接进行一次Full GC,以便让老年去腾出更多的空间,然后再进行Minor GC,把年轻代的对象复制到老年代;如果大于,则根据条件(HandlePromotionFailure设置)进行Minor GC 和 Full GC。
老年区采用标记算法,因为老年区对象的生命周期都是比较长的,采用拷贝算法要拷贝大量的数据。采用标记算法每次gc回收都要遍历所有的对象。
PermGen 主要存放加载进来的类信息,包括方法,属性,常量池等,满了之后可能会引起out of memory 错误。
相关文章推荐
- 剑指 offer代码解析——面试题37两个链表的第一个公共结点
- 剑指 offer代码解析——面试题37两个链表的第一个公共结点
- 盘点国内程序员不常用的热门iOS第三方库
- 机器学习面试题---百度2016春招
- 招聘季福利:掌握这些诀窍,面试成功率增加60%
- 深拷贝的现代写法
- iOS会遇到的面试题(一)
- 面试题60:递归生成格雷码
- 算法面试List
- 我的面试
- 腾讯等面试题
- JAVA程序员必看11本书籍
- 测试人员的职业发展
- mysql优化,不用怕面试题了
- 推荐!国外程序员整理的Java资源大全
- 参加程序员赴美交流收益良多
- 大数乘法的计算原理
- 程序员最应去的网站有哪些?
- 【转】教你如何迅速秒杀99%的海量数据处理面试题
- 周鸿祎:程序员创业成功率极低 他们的能力只是控制机器