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

【Java】【JVM】垃圾回收机制

2017-11-30 16:20 337 查看
// HotSpot虚拟机,虚拟机有很多种实现,HotSpot是指JDK中的虚拟机实现

// GC:Garbage Collection,垃圾回收,即回收内存中不会再被使用的对象

// GC步骤:
// 查找不再被使用的对象
// 释放对象占用的内存

// 查找死对象的方法:
// 引用计数法:记录对象被引用的次数,有新对象引用时,计数+1,有旧引用对象释放时,计数-1
// 根搜索算法:在GC中持续存在的对象称为GC-Roots
// 从这些Root节点向下搜索,经过的路径成为引用链
// 如果所有GC-Root的引用链都不包含一个对象,这个对象就是死对象

// 回收算法:
// 因为对象大小不一样,如果直接回收,剩下的空间就没法容纳更大对象,这样就会产生内存碎片
// 清理算法:标记所有需要清理的对象,然后统一清除(会产生碎片)
// 复制算法:将内存分为两块,一块用完之后,就将上面所有对象,按顺序拷到另一块上面(需要两倍内存)
// 整理算法:清理完死对象后,将所有对象位置向前移动,紧排到一起,然后更新其引用指针(数据移动开销大)

// GC代假设:将JVM堆区域分为新生代和老年代
// 引入代概念,是为了将容易被回收的单独划分出来,从而不用对全部内存进行GC
// 程序规律:大多新创建的对象,很快就会成为死对象,生存时间长的对象,很可能被再次使用
// 新生代存放近期生成的对象,容易被回收
// 老年代存放生存时间比较长的对象,不容易被回收
// 因为大多新手对象很快就被回收了,所以会进入老年代的只是小部分

// MinorGC:在新生代空间内GC
// MajorGC:在老年代空间内GC
// FullGC:在整个空间内GC

// 新生代区域大小很重要:
// 如果新生代过小,会导致新生对象很快就晋升到老年代中,很难被回收
// 如果新生代过大,会发生频繁的复制(新生代使用了复制算法)
// 可以不断通过参数来调整新生代大小,测试程序运行效率,这是内存调优的一种方式

// 新生代空间管理方法:
// 新生代空间分为伊甸区(Eden)和生存区(Survivor)
// 生存区(Survivor)又分为From和To两部分
// 一个新建的对象,会进入Eden区,如果Eden区满了,则会进入From区
// From区中的对象,每经历一次MinorGC,年龄就会增长一岁
// MinorGC时,Eden区的存活对象进入To区,From区中达到指定年龄的进入Old区,未达年龄的进入To区
// 这时Eden区和From区已经被清空,随后将From和To区功能交换,空的From区成为新的To区
// 这样的设计是因为复制算法和代假设的需要,保证了每轮MinorGC后:
// 原From区存活对象长了一岁,旧数据全部在From区,To区重置到最大容量

// 垃圾收集器发展历史:
// Serial(串行)收集器:单线程收集器,进行垃圾收集时,必须暂停其他所有的工作线程
// Parallel(并行)收集器:也称吞吐量收集器,使用多线程降低GC时间
// CMS(并发)收集器:也是多线程,但只在MinorGC时暂停应用,FullGC时不再暂停,而是使用若干后台线程定期对Old空间进行扫描,回收死对象
// G1(并发)收集器:也称垃圾优先收集器,设计初衷是为了尽量缩短处理超大堆时产生的停顿,相对于CMS的优势而言是碎片产生率大大降低

// G1收集器的设计原则就是简单可行的性能调优
// G1收集器仍然属于分代收集器,只是不再将Young,Old分割成独立的两块空间
// 而是将整个堆空间交错地划分为大小不一的Eden,Survivor,Old,Humongous(存放体积大但存活时间短的对象)

// GC效率指标/常见问题:
// 吞吐量:应用程序线程运行时间占总时间的比例,应用线程/(应用线程 + GC线程)
// 暂停时间:GC线程每次执行消耗的时间
// 碎片产生率:内存碎片过小,不能再被利用
// 因为GC总任务量是相对固定的,如果暂停时间太短,则GC次数可能就会增加,吞吐量可能就会下降

// 调优方法:调整GC种类,暂停时间,并发线程数,不同空间的大小比例
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: