JVM学习篇之-GC

原文转自: https://blog.csdn.net/Strong997/article/details/80033787java

一、GC 算法

    垃圾收集 Garbage Collection 一般被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,通过半个多世纪,目前已经十分红熟了。多线程

    jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出作入栈和出栈操做,实现了自动的内存清理,所以,咱们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部份内存的分配和使用都是动态的.并发

二、对象存活判断 jvm

    判断对象是否存活通常有两种方式:性能

        一、引用计数:每一个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时能够回收。此方法简单,没法解决对象相互循环引用的问题。优化

        二、可达性分析(Reachability Analysis):从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证实此对象是不可用的。不可达对象。.net

        在Java语言中,GC Roots包括:线程

            一、虚拟机栈中引用的对象。指针

            二、方法区中类静态属性实体引用的对象。

            三、方法区中常量引用的对象。

           四、 本地方法栈中JNI引用的对象。

三、垃圾收集算法  

    3.1标记 -清除算法

        “标记-清除”(Mark-Sweep)算法,如它的名字同样,算法分为“标记”和“清除”两个阶段:首先标记出全部须要回收的对象,在标记完成后统一回收掉全部被标记的对象。

        它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另一个是空间问题,标记清除以后会产生大量不连续的内存碎片,空间碎片太多可能会致使,当程序在之后的运行过程当中须要分配较大对象时没法找到足够的连续内存而不得不提早触发另外一次垃圾收集动做。

    3.2复制算法

        “复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另一块上面,而后再把已使用过的内存空间一次清理掉。

        这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂状况,只要移动堆顶指针,按顺序分配内存便可,实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半,持续复制长生存期的对象则致使效率下降。

    3.3标记-压缩算法

        “标记-整理”(Mark-Compact)算法,标记过程仍然与“标记-清除”算法同样,但后续步骤不是直接对可回收对象进行清理,而是让全部存活的对象都向一端移动,而后直接清理掉端边界之外的内存

    3.4分代收集算法

        “分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就能够根据各个年代的特色采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少许存活,那就选用复制算法,只须要付出少许存活对象的复制成本就能够完成收集。而老年代中由于对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。
四、垃圾收集器

    4.1串行垃圾回收器Serial        

        串行回收器是指使用单线程进行垃圾回收的回收器,每次回收时串行回收器只有一个工做线程,对于并发能力较弱的计算机来讲,串行回收器的专一性和独占性每每有更好的表现。串行回收器能够在新生代和老年代使用,根据做用的堆空间不一样,分为新生代串行回收器和老年代串行回收器。

        Serial收集器是最古老的收集器,它的缺点是当Serial收集器想进行垃圾回收的时候,必须暂停用户的全部进程,即stopthe world(服务暂停)。到如今为止,它依然是虚拟机运行在client模式下的默认新生代收集器。

        参数控制:-XX:+UseSerialGC 使用串行收集器    


    4.2并行垃圾回收器 

        4.2.1并行垃圾回收器

                并行回收器是在串行回收器的基础上作了改进,它可使用多个线程同时进行垃圾回收,对于计算能力强的计算机来讲,能够有效的缩短垃圾回收所需的实际时间        
        4.2.2并行垃圾回收器——ParNew

                ParNew收集器是一个工做在新生代的垃圾收集器,它只是简单的将串行收集器多线程化,它的回收策略和算法和串行回收器同样。新生代并行,老年代串行;新生代复制算法、老年代标记-压缩。

                参数控制:-XX:+UseParNewGC 使用ParNew收集器     -XX:ParallelGCThreads 限制线程数量

        4.2.3并行垃圾回收器——Parallel

                Parallel是采用复制算法的多线程新生代垃圾回收器,Parallel收集器更关注系统的吞吐量。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)。

                停顿时间越短就越适合须要与用户交互的程序,良好的响应速度可以提高用户的体验;

                而高吞吐量则能够最高效率地利用CPU时间,尽快地完成程序的运算任务,主要适合在后台运算而不须要太多交互的任务。

                能够经过参数来打开自适应调节策略,虚拟机会根据当前系统的运行状况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量;也能够经过参数控制GC的时间不大于多少毫秒或者比例;新生代复制算法、老年代标记-压缩

                参数控制:-XX:MaxGCPauseMillis 设置最大垃圾收集停顿时间    -XX:GCTimeRatio 设置吞吐量的大小(默认是99)    -XX:+UseAdaptiveSeizPolicy 打开自适应模式

        4.2.4并行垃圾回收器——Parallel Old

                Parallel Old收集器是Parallel Scavenge收集器的老年代版本,采用多线程和”标记-整理”算法,也是比较关注吞吐量。在注重吞吐量及CPU资源敏感的场合,均可以优先考虑Parallel Scavenge加Parallel Old收集器。

                参数控制:-XX:+UseParallelOldGC 使用ParallelOld收集器    -XX:ParallelGCThreads 限制线程数量

    4.3CMS垃圾回收器

        CMS(Concurrent Mark Sweep)并发标记请除,它使用的是标记请除法,工做在老年代,主要关注系统的停顿时间。

        CMS并非独占的回收器,也就是说,CMS回收的过程当中应用程序仍然在不停的工做,又会有新的垃圾不断的产生,因此在使用CMS的过程当中应该确保应用程序的内存足够可用,CMS不会等到应用程序饱和的时候才去回收垃圾,而是在某一阀值(默认为68)的时候开始回收,也就是说当老年代的空间使用率达到68%的时候回执行CMS。若是内存使用率增加很快,在CMS执行过程当中,已经出现了内存不足的状况,此时,CMS回收就会失败,虚拟机将启动老年代串行回收器进行垃圾回收,这会致使应用程序中断,直到垃圾回收完成后才会正常工做,这个过程GC的停顿时间可能较长,因此阀值的设置要根据实际状况设置。

        标记清除法的缺点是内存碎片问题,CMS提供提供了一些优化设置,能够设置完成CMS以后进行一次碎片整理,也能够设置进行多少次CMS回收后进行碎片整理

        参数控制:-XX:CMSInitatingPermOccupancyFraction 设置阀值    -XX:+UserConcMarkSweepGC 使用cms垃圾清理器    -XX:ConcGCThreads 限制线程数量    -XX:+UseCMSCompactAtFullCollection 设置完成CMS以后进行一次碎片整理    -XX:CMSFullGCsBeforeCompaction 设置进行多少次CMS回收后进行碎片整理

    4.4G1(Garbage First)垃圾回收器

        G1(Garbage First)垃圾收集器是当今垃圾回收技术最前沿的成果之一。早在JDK7就已加入JVM的收集器你们庭中,成为HotSpot重点发展的垃圾回收技术。同优秀的CMS垃圾回收器同样,G1也是关注最小时延的垃圾回收器,也一样适合大尺寸堆内存的垃圾收集,官方也推荐使用G1来代替选择CMS。G1最大的特色是引入分区的思路,弱化了分代的概念,合理利用垃圾收集各个周期的资源,解决了其余收集器甚至CMS的众多缺陷。

        并行与并发:G1能充分利用多CPU、多核环境下的硬件优点,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿的时间,部分其余收集器本来须要停顿Java线程执行的GC动做,G1收集器仍然能够经过并发的方式让Java程序继续执行。

        分代收集:与其余收集器同样,分代概念在G1中依然得以保留。虽然G1能够不需其余收集器配合就能独立管理整个GC堆,但它可以采用不一样的方式去处理新建立的对象和已经存活了一段时间、熬过屡次GC的旧对象以获取更好的收集效果。

        空间整合:与CMS的“标记-清理”算法不一样,G1从总体看来是基于“标记-整理”算法实现的收集器,从局部(两个Region之间)上看是基于“复制”算法实现,不管如何,这两种算法都意味着G1运做期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会由于没法找到连续内存空间而提早触发下一次GC。

        可预测的停顿:这是G1相对于CMS的另一大优点,下降停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能创建可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片断内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已是实时Java(RTSJ)的垃圾收集器特征了。

        参数控制:-XX:+UseG1GC 使用G1垃圾收集器    -XX:ParallelGCThreads 限制线程数量    -XX:MaxGCPauseMillis 指定最大停顿时间

相关文章
相关标签/搜索