内容简介:Java垃圾回收机制
JVM 框架
Java虚拟机HotSpot的框架:
JVM主要组成部分:Class Loader(类加载器)、Runtime Data Area(运行时数据区)、执行引擎(Execution Engine)。
JVM 垃圾回收简介
Step 1: Marking
GC算法在扫描存活对象时通常需要从Root节点开始,扫描所有存活对象的引用,构建出对象图。
Root:静态字段、方法参数、局部变量、CPU寄存器
Step 2: Normal Deletion
删除没有被引用的对象,释放空间。
Step 2a: Deletion with Compacting
删除垃圾并压缩存活的引用对象,有利于提高内存分配的效率。
Generational Garbage Collection (分代垃圾回收)
HotSpot堆结构:
Young Generation:从eden区分配新对象,eden区满后,发生一次minor garbage collection,把eden区和一个survivor区中存活的对象移动到另一个survivor区中,存活的对象age加1,当存活的对象age达到一个阈值时晋升到Old Generation。
Old Generation:保存存活长久对象的地方,Old Generation满后会发生major garbage collection(full garbage collection)。
Stop the World Event:minor garbage collection和major garbage collection都是Stop the World Event,即垃圾回收的时候会暂停程序中线程的执行。
Permanent generation:保存JVM中用于描述类和方法的元数据信息。
整个GC的流程总结图:
GC分代的基本假设是:绝大部分对象的生命周期都非常短暂,存活时间短。
分配小对象的开销负担小,不要吝啬去创建。
GC最喜欢这种小而短命的对象。
让对象的生命周期尽可能短,例如在方法体内创建,使其能尽快地在YoungGC中被回收,不会晋升(romote)到年老代(Old Generation)。
对象分配的优化:尽量避免大对象的分配,当对象大到Eden Generation放不下时,JVM只能尝试去Old Generation分配,这种情况需要尽可能避免,因为一旦在Old Generation分配,这个对象就只能被Old Generation的GC或是FullGC回收了。
不可变对象可以减少GC的压力:Hotspot JVM为了提高YoungGC的性能,避免每次YoungGC都扫描Old Generation中的对象引用,采用了卡表(Card Table) 的方式。简单来说,当Old Generation中的对象发生对Young Generation中的对象产生新的引用关系或释放引用时,都会在卡表中响应的标记上标记为脏(dirty),而YoungGC时,只需要扫描这些dirty的项就可以了。可变对象对其它对象的引用关系可能会频繁变化,并且有可能在运行过程中持有越来越多的引用,特别是容器。这些都会导致对应的卡表项被频繁标记为dirty。而不可变对象的引用关系非常稳定,在扫描卡表时就不会扫到它们对应的项了。
指定容器初始化大小可以减少GC的压力:每次容器扩容分配更大的空间,可能会增加GC的次数。
各类引用:java.lang.ref.Reference有几个子类,用于处理和GC相关的引用。JVM的引用类型简单来说有几种:
Strong Reference,最常见的引用。
Weak Reference,当没有指向它的强引用时会被GC回收。
Soft Reference,只当临近OOM时才会被GC回收。
Phantom Reference,主要用于识别对象被GC的时机,通常用于做一些清理工作。
Garbage Collector(垃圾收集器)
JVM中会在以下情况触发回收:对象没有被引用,作用域发生未捕捉异常,程序正常执行完毕,程序执行了System.exit(),程序发生意外终止。
JVM中标记垃圾使用的算法是一种根搜索算法。简单的说,就是从一个叫GC Roots的对象开始,向下搜索,如果一个对象不能达到GC Roots对象的时候,说明它可以被回收了。这种算法比一种叫做引用计数法的垃圾标记算法要好,因为它避免了当两个对象啊互相引用时无法被回收的现象。
JVM中对于被标记为垃圾的对象进行回收时又分为了一下3种算法:
1.标记清除算法,该算法是从根集合扫描整个空间,标记存活的对象,然后在扫描整个空间对没有被标记的对象进行回收,这种算法在存活对象较多时比较高效,但会产生内存碎片。
2.复制算法,该算法是从根集合扫描,并将存活的对象复制到新的空间,这种算法在存活对象少时比较高效。
3.标记整理算法,标记整理算法和标记清除算法一样都会扫描并标记存活对象,在回收未标记对象的同时会整理被标记的对象,解决了内存碎片的问题。
HotSpot 1.6版使用的垃圾收集器如下图(图中两个收集器之间有连线,说明它们可以配合使用):
1.Serial GC
从名字上看,串行GC意味着是一种单线程的,所以它要求收集的时候所有的线程暂停。这对于高性能的应用是不合理的,所以串行GC一般用于Client模式的JVM中。
2.ParNew GC
是在SerialGC的基础上,增加了多线程机制。但是如果机器是单CPU的,这种收集器是比SerialGC效率低的。
3.Parrallel Scavenge GC
这种收集器又叫吞吐量优先收集器,而吞吐量=程序运行时间/(JVM执行回收的时间+程序运行时间),假设程序运行了100分钟,JVM的垃圾回收占用1分钟,那么吞吐量就是99%。Parallel Scavenge GC由于可以提供比较不错的吞吐量,所以被作为了server模式JVM的默认配置。
4.ParallelOld
是老生代并行收集器的一种,使用了标记整理算法,是JDK1.6中引进的,在之前老生代只能使用串行回收收集器。
5.Serial Old
是老生代client模式下的默认收集器,单线程执行,同时也作为CMS收集器失败后的备用收集器。
6.CMS(Concurrent Mark Sweep)
又称响应时间优先回收器,使用标记清除算法,同时它又是一个使用多线程并发回收的垃圾收集器。他的回收线程数为(CPU核心数+3)/4,所以当CPU核心数为2时比较高效些。CMS分为4个过程:初始标记、并发标记、重新标记、并发清除和并发重置。其中初始标记和重新标记是独占系统资源的,而并发标记、并发清除和并发重置是可以和用户线程一起执行的。因此,从整体上来说,CMS 收集不是独占式的,它可以在应用程序运行过程中进行垃圾回收。
7.Garbage First(G1)
比较特殊的是G1回收器既可以回收Young Generation,也可以回收Tenured Generation。它是在JDK6的某个版本中才引入的,性能比较高,同时注意了吞吐量和响应时间。与CMS收集器相比,G1收集器是基于标记-压缩算法的。因此,它不会产生空间碎片,也没有必要在收集完成后,进行一次独占式的碎片整理工作。
对于垃圾收集器的组合使用可以通过下表中的参数指定:
参考:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
http://coolshell.cn/articles/11541.html
http://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/index.html
http://www.importnew.com/16388.html
本文转自阿凡卢博客园博客,原文链接:http://www.cnblogs.com/luxiaoxun/p/4631575.html ,如需转载请自行联系原作者
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Coding the Matrix
Philip N. Klein / Newtonian Press / 2013-7-26 / $35.00
An engaging introduction to vectors and matrices and the algorithms that operate on them, intended for the student who knows how to program. Mathematical concepts and computational problems are motiva......一起来看看 《Coding the Matrix》 这本书的介绍吧!