JVM探究

常见的GC算法

      手动内存管理    和引用计数法    

      垃圾收集根元素  :

             局部变量    活动线程    静态域   jni引用     其他对象

              jvm使用标记清除来跟踪所有可达对象 (存活对象)   确保所有不可达对象占用的内存可以重用         其中包含两步:   标记    清除

              标记:遍历所有可达对象     并在本地内存中分门别类记下

              清除:保证不可达对象所占用的内存,在之后内存分配的过程中可以得到重用

                这两个步骤不在因为循环引用而导致内存泄漏

             标记清除最标准的垃圾收集算法 ,这种处理方式不好的地方在于:垃圾收集过程需要暂停所有的应用程序线程。不暂停引用关系一直改变 ,无法进行统计。这种情况叫做STW停顿

                碎片整理:   写入操作越来越耗时 寻找一个大的空间变得困难   

                                   创建新对象时 在连续的块中分配内存。碎片化严重,直至没有空闲片段能放下新创建的对象,就会发生内存分配错误。

                                     
垃圾收集器的    具体实现

     一般使用两种不一样的GC算法  一种清理年轻代  一种清理老年代

      串行GC   :年轻代使用标记  复制   

                          老年代 标记清除 整理

                          两者都是单线程的垃圾收集器 不能进行并行处理,所以会触发全线暂停 停止应用线程        不能充分利用多核cpu,因为每次只启动一个核心

                          只需要启动一个jvm参数  同时对  年轻代  老年代生效

                          适合几百MB的堆内存的JVM,而且是单核cpu时比较有用

       

        并行GC:年轻代   标记-复制       老年轻  标记 清除  整理    执行阶段都使用多个线程  通过并行执行,使得GC时间大大减少

                      

 

 适用于多核服务器    主要增加吞吐量   对系统资源的有效使用

. ..gc期间,所有cpu并行清理垃圾,所以总暂停的时间更短

....两次gc的间隔期,没有gc线程在运行,不会消耗任何系统资源

并行gc容易出现长时间的卡顿    mgc毫米级别    fgc几十几百毫秒级别

长时间卡顿的意思是:gc启动后 ,属于一次性完成所有操作,于是单次暂停时间会比较长

          

CMS垃圾收集器

         最大并发-标记-清除  垃圾收集器   年轻代采用stw方式的 标记-复制算法,对老年代主要使用标记-清除算法

         CMS GC的设计目标 是避免在老年代垃圾收集时出现长时间的停顿,主要通过俩种手段来达成此目标:

          第一:对老年代不进行整理,而是用空闲列表来管理内存空间的回收

          第二: 在标记清除阶段的大部分工作和应用线程一起并发执行

         这个阶段没有明显的应用线程暂停,但是仍然和应用线程争抢cpu时间。默认情况下,CMS使用的并发线程数等于cpu核心数的1/4

     

 如果服务器是多核

 

 cpu,并且调优的目标是降低GC停顿导致的系统延迟,那么cms是个很明智的选择

并且通过减少每一次GC停顿时间,可以直接改善系统的用户体验。

       

CMS GC的几个阶段:

       阶段1:初始标记    

       

 

   阶段2:并发标记:

      并发标记阶段就是  应用程序同时运行,不用暂停的阶段。并不是所有老年代存活的对象都会被标记,因为对象的引用关系还在发生变化

   阶段3:并发预清理    jvm卡片的方式将改变的区域标记为脏区,这就是所谓的卡片标记

 

阶段4: 阶段可取消的并发预清理:

       

 

 

阶段5:最终标记

 最终标记阶段是第二次 gc事件中的第二次STW停顿

本阶段目标是完成老年代中所有的存活对象标记    因为之前的预清理阶段是并发执行的,有可能线程执行速度  跟不上应用线程更改的速度。   所以需要一次STW暂停来处理各种复杂的情况。

       通常CMS尝试在年轻代尽可能空的情况下执行 Final Remark阶段,避免连续触发STW事件   在五个阶段完成后,老年代中所有的对象都被标记了,然后gc将清除所有不使用的对象来回收老年代空间。

 

阶段6:并发清除

此阶段与应用程序并发执行,不需要STW停顿  。jvm此阶段删除不在使用的对象,并回收他们占用的空间。

阶段7:并发重置

并发执行  重置CMS算法的相关内部数据,为下一次GC做准备

 

 

G1垃圾收集器

垃圾优先,哪里垃圾最多清理哪里

G1gc 最主要的设计目标是:将STW停顿的时间和分布,变成可预期且可配置的

是一款软实时垃圾收集器  可以设置某项特定的性能指标   。

可以任意毫秒内STW不超过yy毫秒

堆不在分为年轻代  老年代  划分为可以存放对象的小堆块区域

 

 

 

 

 

 

 

 

  G1会通过前面一段时间的运行情况不断调整自己的回收策略和行为     刚启动时处于初始的FULLY-young模式,年轻代用满时,应用线程会被暂停,年轻代内存块中的存活对象拷贝到存活期。拷贝过程叫转移。

   

并发标记:

   G1的并发标记通过起始快照的方式,在标记阶段开始记下所有存活对象。通过对象的存活信息,可以构建每个小块的存活状态,以便高效的收集。

         

 

阶段1:初始标记

          标记从根对象直接可达的对象。在CMS中需要一次STW暂停,但G1里面通常是在转移暂停的同时处理这些事情,所以开销很小的。

阶段2:root区扫描

          标记所有从root区直接可达的对象。

阶段3:并发标记

          只遍历对象图,并在特殊的位图中标记能访问到的对象。

阶段4:再次标记

           stw停顿,已完成标记过程

阶段5:清理

       

 

 

转移暂停:混合模式

           并发标记完成后,G1将执行一次混合收集,不止清理年轻代,还将一部分老年代也加入会收集中。

历史记忆集:

           用来支持不同小块进行独立回收

 

 

 

 

 

 

                   

posted @ 2022-04-19 16:10  李文浩learning  阅读(34)  评论(0)    收藏  举报