hotspot的JVM中的垃圾回收

有很多有名的Jvm,但我们最常用到的就是Oracle收购sun公司的HotSpot。

HotSpot中内存被分为3个代:年轻代(young generation),年老代(old generation),持久代(permanent generation)。对象最初在年轻代,年老代代理存放着是经过几次年轻代收集后仍然 live 的对象和一些可能直接被分配到年老代的大对象。持久代存放的是 JVM 认为可以帮助简化垃圾收集管理的对象,比如像类和方法的描述信息。

 

年轻代代内存模型:一个伊甸区(Eden),加上两个小代生还区(survivor space)

wKiom1bphpKjQgYqAABr_eWR7GU051.png

大部分对象是直接分配在伊甸区(有一些大的对象可能直接分配在年老代),最后一次垃圾回收后还生存代对象保存在生还区,它们在晋升到年老代之前还是有可能会死掉。这种对象被保存在from区中。

一个收集器可能会有多个算法,一些用于年轻代,一些用于年老代。但除了CMS收集器,其它代收集器会在年轻代使用年老代的收集算法,每当年老代被占用代太慢了。CMS收集器没有这样的原因是因为CMS算法不能用于在年轻代上。

 

快速分配:在很多情况下都存在一个连续的很大的内存块用于分配。这时候可以用一种被称之为空闲指针的简单点技术在这块内存上进行分配。这种技术就是用一个指针来保存每次分配的痕迹,当再次有分配的请求时,就检查新对象是否可以放下,如果能就更新指针初始化对象。

 

 

下面介绍几种收集器:

 

串行收集(Serial Collector):

        不管年轻代还是年老代都是串行代,就是只使用一个cpu,这种收集器使用的是停止一切的模式。

 

串行收集器的年轻代工作步骤:

        在伊甸区存活的对象除了太大的不适合放入的对象都要复制到TO生还区,那些太大的对象直接放入了年老代。另一个from生还区中对象较为年轻代也放入了TO生还区,年老的则复制到了年老代。如果TO区满了的话,就无法在放入了,满、那么伊甸区和from区的存活的对象直接晋升到年老代。复制完成后不需要任何检查,因为留在伊甸区和From区的都不是存活的对象。(这里没有使检查或标记的算法)

wKiom1bphs7AsQWyAACS2UcHKmc361.png

在年轻代收集完一次之后,伊甸区和From区里都是空的了,只有To区海有对象,这时两个生化区交换角色。

 

串行收集器的年老代工作步骤:

        使用标记-清扫-压缩的算法。标记是:标记收集器中海油哪些对象是和根节点向连的,是存活的。清扫是:扫荡整个代识别垃圾。压缩是:移动压缩,将存活的对象移动到代的前端,在末尾留下一整块的连续的空间空间,之后就可以泗洪 空闲指针来标记。

 

在什么时候使用这种串行的收集器?

        一般都是在客户端环境(非服务器级别动),对短暂停可以忍受的程序中。java视频现在串行收集器可以有效的管理拥有64M堆内存的应用程序。

串行收集器可以使用  -XX:UseSerialGC 指令来指出我要使用串行收集器。

 

 

并行收集器(Parallel Collector):

        先如今基本上都是多核处理的机器,这样随之有利用多核优势的收集器被设计出来,不至于让许多cpu处于空闲状态。

 

并行收集器的年轻代:

        和串行不同的是,这里使用的是串行年轻代收集的一个并行的版本,也仍然是 stop the world的复制算法。但使用了多个cpu,因此是很快的,增加了吞吐量。

wKioL1bph4HAMRdgAABd0Wm4R5o143.png

 

并行收集器的年老代和串行的一样。

 

 

并行压缩收集器(Paralle Compacting Collector):

        它于并行收集不同地方就在在年老代上的收集使用了一种新的算法。

 

并行压缩的年老代收集:

使用的是并行的平行压缩算法和stop the world模式。此算法可以分为三个阶段:

     

    标记阶段,在最初的应用程序中代码能够直接到达的对象分给垃圾回收线程,然后开始并行的标记所有这些能够直接到达(活着)的对象,如果一个对象是活着的,那么这个对象的大小和所在的位置就会更新在它的区域数据中。

 

     摘要阶段,作用在区域上,而不是对象上:通常经过几个周期短压缩后每个代代左侧是很稠密的,存放着的对象大部分都是活着的,所以压缩它们是很不值得的。所以在这个阶段收集器所做的第一件事情就是要检查区域的密度,加入密度达到某一个值时,从这个点及其右侧到区域都要进行垃圾回收(压缩)。在这个阶段计算的是每个被压缩区域中的存活对象的第一个字节的位置。

 

     压缩阶段,垃圾收集线程是要利用再要数据确定哪些适区域是要填满的,然后每个线程对立的拷贝数据到对应的区域中。最后产生一个在一端很稠密在一段很大的空闲空间

 

     ps:我的理解,标记阶段和摘要阶段实在为压缩阶段做准备,标记阶段是先找到一个大概的位置,摘要阶段是确定哪些是需要进行压缩的,最后在到压缩阶段进行压缩。

 

何时使用并行压缩:

     并行压缩收集器就是在并行收集器上在年老代的时候多使用了个并行的压缩算法,这使得它在多个cpu的机器上拥有更好的性能,比如能够减少暂停时间。这种收集器不适合仔大型共享机器上运行程序,因为这些机器上一个程序不能独占多个cpu太长时间,在这些机器上应当考虑减少垃圾收集线程(使用命令行参数 -XX:ParallelGCThreads=n)或者选择不同的收集器。如果想使用这个收集器,可以通过使用命令行参数:

—XX:UseParalleOldGC

posted @ 2016-03-18 08:23  jinshiyill  阅读(638)  评论(0编辑  收藏  举报