所有示例均在gihub(ssh_base)中====>https://github.com/chengyangyang

JVM 垃圾回收机制

 

  吞吐量:CPU运行代码的时间和CPU 总共消耗时间的比值。

  

  在Java中,我们知道,内存的分布主要式堆和栈,栈会随着线程的结束而销毁,因此我们不需要考虑栈内存的回收,我们只需要考虑堆的垃圾回收,忽略其他内存的回收。 

  在JVM 运行的不同时期,使用不同的垃圾回收算法。

  在Java 中,并没有明确的说明JVM使用哪种垃圾回收算法,但是任何一种垃圾回收算法都必须做两种事:

  ① 发现无用的信息对象 ②回收无用的垃圾对象占用的内存

  在这之前,我们首先要了解垃圾收集器和垃圾回收器算法,在虚拟机中,我们可以选择一种垃圾回收器,每种垃圾回收器使用不同的算法进行回收。

  

jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.9 默认垃圾收集器G1



-XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型

-XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断

 

  垃圾回收器的算法:

  引用计数算法

    给对象中添加一个引用计数器,每当一个地方引用他的时候,计数器就加一,当引用失效的时候,计数器就减一(这个算法实现简单/效率高,但是有个缺陷很难解决相互引用的问题)

  可达性分析算法

    通过起始节点GC roots ,从这些节点往下搜索,搜索所走过的路径引用连接,当一个对象中没有任何引用链相连接,则证明对象不可用

    在Java语言中,可作为roots 的有:①虚拟机栈中的引用对象 ② 方法区中静态属性的引用对象 ③ 方法区中常量引用对象 ④本地方法栈中引用的对象

    在这过程中,当内存空间足够的话,我们希望能够保留在内存中,所以java就对引用进行了扩充,就是强引用/软引用/弱引用/虚引用  

    当对象不可达时,他们并非时非死不可,要宣告死亡,最少要经历2次标记的过程, 第一次标记并筛选条件是,是否有必要执行finalize(),当对象没有覆盖这个方法,或者这个方法已经被虚拟机调用过了,则判断没有必要执行,

    当有必要执行执行,放入队列等待清除,在这过程中,对象可能会逃脱出来。

  标记-清除算法

    算法分为标记和清除两部分,首先标记出所有需要清除的对象,在标记完成之后, 同意回收所有被标记的对象。(标记和清除效率并不高)

  复制算法

    为了解决效率的问题,这种算法出现了,他将可用内存按照大小分为两部分,每次只使用其中的一块,当这块的内存使用完之后,就将还存活的对象复制到另外一块上面,然后把已经使用过的内存空间一次性清理掉,(简单高效,但是内存缩小为原先一半)

    这样是对整个半内存进行回收,也不用考虑碎片的问题。

    研究表明,新生代中的对象98% 是朝生夕死,所有没有必要按照1:1 进行分配,而是将内存分配为一个较大的Eden 和两块较小的Survivor ,当进行回收的时候,将Eden 和其中一块Survivor 还存活的对象一次性复制到另外一块Survivor 上面,然后清理掉

    刚才那两块内存,这样就相当于只有10% 的内存会被浪费,如果另外一块内存没有足够的空间保存存活的对象,会将这些对象通过分配机制进入老年代,

  标记整理算法

    复制算法是在对象存活相对较高的情况下,复制效率会变低,更关键的是如果不想浪费内存,就需要额外的内存担保,所以老年代中一般不会选用这样算法

   标记过程仍然和标记-清除相同,但是后续不同,就是让所有存活的对象都向一端进行移动,然后直接清理掉界限以外的数据。

  分代收集算法

    根据对象的存活周期,将内存分为几块,然后分别使用不同的算法 

  


 

    GC 日志

    每一个收集器日志的格式都不相同,但为了方便,各个之间也有共性     -XX:+PrintGCDetails 可以进行查看

    

[GC (Metadata GC Threshold) [PSYoungGen: 26326K->4600K(61952K)] 30735K->11354K(138752K), 0.0121680 secs] [Times: user=0.01 sys=0.01, real=0.01 secs] 
[Full GC (Metadata GC Threshold) [PSYoungGen: 4600K->0K(61952K)] [ParOldGen: 6754K->7125K(48128K)] 11354K->7125K(110080K), [Metaspace: 20582K->20580K(1067008K)], 0.0652552 secs] [Times: user=0.09 sys=0.00, real=0.07 secs] 

    GC和Full GC 是区分垃圾收集的停顿类型

  PSYoungGen 发生的区域
   26326K->4600K(61952K)   GC前该内存区域已经使用容量-> GC后该区域使用区域容量(该内存区域的总容量)
  方括号外面 30735K->11354K(138752K) GC 前堆已经使用容量->GC后堆使用容量(堆总容量)
  0.0121680 secs 在该内存区域垃圾回收占用的时间,单位是秒

  
参数描述
UseSerialGC 虚拟机运行在Client模式下的默认值,打开此开关后,使用Serial + Serial Old的收集器组合进行内存回收
UseParNewGC 打开此开关后,使用ParNew + Serial Old的收集器组合进行内存回收
UseConcMarkSweepGC 打开此开关后,使用ParNew + CMS + Serial Old的收集器组合进行内存回收。Serial Old收集器将作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用
UseParallelGC 虚拟机运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge + Serial Old(PS MarkSweep)的收集器组合进行内存回收
UseParallelOldGC 打开此开关后,使用Parallel Scavenge + Parallel Old 的收集器组合进行内存回收
SurvivorRatio 新生代中Eden区域与Survivor区域的容量比值,默认为8,代表Eden : Survivor=8:1
PretenureSizeThreshold 直接晋升到老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配
MaxTenuringThreshold 晋升到老年代的对象年龄。每个对象在坚持过一次Minor GC之后,年龄就增加1,当超过这个参数值时就进入老年代
UseAdaptiveSizePolicy 动态调整Java堆中各个区域的大小以及进入老年代的年龄
HandlePromotionFailure 是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个Eden和Survivor区的所有对象都存活的极端情况
ParallelGCThreads 设置并行GC时进行内存回收的线程数
GCTimeRatio GC时间占总时间的比率,默认值为99,即允许1%的GC时间。仅使用Parallel Scavenge收集器时生效
MaxGCPauseMillis 设置GC的最大停顿时间。仅在使用Parallel Scavenge收集器生效
CMSInitiatingOccupancyFraction 设置CMS收集器在老年代空间被使用多少后触发垃圾收集,默认值为68%,仅使用CMS收集器时生效
UseCMSCompactAtFullCollection 设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅在使用CMS收集器时生效
CMSFullGCsBeforeCompaction 设置CMS收集器在进行若干次垃圾收集后再启动一次内存碎片整理。仅在使用CMS收集器时生效
posted @ 2019-07-23 11:02  ☞书香门第☜  阅读(234)  评论(0编辑  收藏  举报
http://count.knowsky.com/count1/count.asp?id=434520&sx=1&ys=64"