`

JVM 垃圾回收机制与GC性能调优

    博客分类:
  • Java
阅读更多

一篇还不错的分析。网上可查到很多转载,原文系谁所作已不可考,现只能列出我看到的发布时间最早的链接:

转载自: http://dinghaoliang.blog.163.com/blog/static/12654071420098711273543/

 

一、GC概要:

JVM堆相关知识

    为什么先说JVM堆?

    JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象。这些对象的建立方式就是那些new一类的操作,当对象无用后,是GC来负责这个无用的对象(地球人都知道)。

JVM堆

    (1) 新域:存储所有新成生的对象

    (2) 旧域:新域中的对象,经过了一定次数的GC循环后,被移入旧域

    (3)永久域:存储类和方法对象,从配置的角度看,这个域是独立的,不包括在JVM堆内。默认为4M(这个应该是Perm Space吧)。

新域会被分为3个部分:1.第一个部分叫Eden。(伊甸园??可能是因为亚当和夏娃是人类最早的活动对象?)2.另两个部分称为辅助生存空间(幼儿园),我这里一个称为A空间(From sqace),一个称为B空间(To Space)

JVM 垃圾回收机制与GC性能调优 - dean - dinghaoliang 的博客GC浅谈:

GC的工作目的很明确:在堆中,找到已经无用的对象,并把这些对象占用的空间收回使其可以重新利用.大多数垃圾回收的算法思路都是一致的:把所有对象组成一个集合,或可以理解为树状结构,从树根开始找,只要可以找到的都是活动对象,如果找不到,这个对象就是凋零的昨日黄花,应该被回收了。

在sun 的文档说明中,对JVM堆的新域,是采用coping算法,该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。它开始时把堆分成一个对象面和多个空闲面,程序从对象面为对象分配空间,当对象满了,基于 coping算法的垃圾收集就从根集中扫描活动对象,并将每个活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存。

对于新生成的对象,都放在Eden中;当Eden充满时(小孩太多了),GC将开始工作,首先停止应用程序的运行,开始收集垃圾,把所有可找到的对象都复制到A空间中,一旦当A空间充满,GC就把在A空间中可找到的对象都复制到B空间中(会覆盖原有的存储对象),当B空间满的时间,GC就把在B空间中可找到的对象都复制到A空间中,AB在这个过程中互换角色,那位客官说了:拷来拷去,烦不烦啊?什么时候是头?您别急,在活动对象经过一定次数的GC操作后,这些活动对象就会被放到旧域中。对于这些活动对象,新域的幼儿园生活结束了。

新域为什么要这么折腾?

起初在这块我也很迷糊,又查了些资料,原来是这样:应用程序生成的绝大部分对象都是短命的,copying算法最理想的状态是,所有移出Eden的对象都会被收集,因为这些都是短命鬼,经过一定次数的GC后应该被收集,那么移入到旧域的对象都是长命的,这样可以防止AB空间的来回复制影响应用程序。

实际上这种理想状态是很难达到的,应用程序中不可避免地存在长命的对象,copying算法的发明者要这些对象都尽量放在新域中,以保证小范围的复制,压缩旧域的开销可比新域中的复制大得多(旧域在下面说)。

对于旧域,采用的是tracing算法的一种,称为标记-清除-压缩收集器,注意,这有一个压缩,这是个开销挺大的操作。

垃圾回收主要是对Young Generation块和Old Generation块内存进行回收,YG用来放新产生的对象,经过几次回收还没回收掉的对象往OG中移动,对YG进行垃圾回收又叫做MinorGC,对OG垃圾回收又叫MajorGC,两块内存回收互不干涉

二、Gc 流程:

[older generation][survivor 1][survivor 2][eden]

*young generation=eden + survivor

1.当eden满了,触发young GC;

2.young GC做2件事:一,去掉一部分没用的object;二,把老的还被引用的object发到survior里面,等下几次GC以后,survivor再放到old里面。

3.当old满了,触发full GC。full GC很消耗内存,把old,young里面大部分垃圾回收掉。这个时候用户线程都会被block。

 

三、young generation比例越大,不一定最好。

将young的大小设置为大于总堆大小的一半时会造成效率低下。如果设置得过小,又会因为young generation收集程序不得不频繁运行而造成瓶颈。

 

四、总结

从上面的推导可以得出很多结论,下面是前辈的经验总结与自已的认识

1.JVM堆的大小决定了GC的运行时间。如果JVM堆的大小超过一定的限度,那么GC的运行时间会很长

2.对象生存的时间越长,GC需要的回收时间也越长,影响了回收速度。

3.大多数对象都是短命的,所以,如果能让这些对象的生存期在GC的一次运行周期内,wonderful!

4.应用程序中,建立与释放对象的速度决定了垃圾收集的频率。

5.如果GC一次运行周期超过3-5秒,这会很影响应用程序的运行,如果可以,应该减少JVM堆的大小了。

6.前辈经验之谈:通常情况下,JVM堆的大小应为物理内存的80%

五、看案例:

jmap -heap 2343

Attaching to process ID 2343, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 11.0-b16

using thread-local object allocation.

Parallel GC with 8 thread(s)

Heap Configuration:

   MinHeapFreeRatio = 40

   MaxHeapFreeRatio = 70

   MaxHeapSize      = 4294967296 (4096.0MB)

   NewSize          = 2686976 (2.5625MB)

   MaxNewSize       = -65536 (-0.0625MB)

   OldSize          = 5439488 (5.1875MB)

   NewRatio         = 2                  (YG,OG 大小比为1:2)

   SurvivorRatio    = 8

   PermSize         = 21757952 (20.75MB)

   MaxPermSize      = 268435456 (256.0MB)

Heap Usage:

PS Young Generation

Eden Space:

   capacity = 1260060672 (1201.6875MB)

   used     = 64868288 (61.86322021484375MB)

   free     = 1195192384 (1139.8242797851562MB)

   5.148028935546367% used

From Space:

   capacity = 85524480 (81.5625MB)

   used     = 59457648 (56.70323181152344MB)

   free     = 26066832 (24.859268188476562MB)

   69.52120375359195% used

To Space:

   capacity = 85852160 (81.875MB)

   used     = 0 (0.0MB)

   free     = 85852160 (81.875MB)

   0.0% used

~~~~~~~~~~~~~~~~~~~~~~~~~~这三块为上面所说的YG大小和使用情况

PS Old Generation

   capacity = 2291138560 (2185.0MB)

   used     = 1747845928 (1666.8757705688477MB)

   free     = 543292632 (518.1242294311523MB)

   76.28722062099989% used

~~~~~~~~~~~~~~~~~~~~~~~~~~OG大小和使用情况

PS Perm Generation

   capacity = 108265472 (103.25MB)

   used     = 107650712 (102.6637191772461MB)

   free     = 614760 (0.5862808227539062MB)

   99.43217353728436% used

这台机器简单说YG内存1G,OG内存2G,总内存4G

在这样的配置下,GC运行情况:

jstat -gcutil -h5 2343 4s 100

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT  

 79.82   0.00  75.34  78.55  99.44   7646 1221.668   398 2052.993 3274.661

  0.00  79.52   0.62  78.63  99.44   7647 1221.782   398 2052.993 3274.775 这里发生了一次YG GC,也就是MinorGC,耗时0.12s

  0.00  79.52  28.95  78.63  99.44   7647 1221.782   398 2052.993 3274.775

  0.00  79.52  46.34  78.63  99.44   7647 1221.782   398 2052.993 3274.775

同时可以看到总共进行了398次Major GC 总耗时2052.993 所以每次Major GC时间为:2052.993/398=5.16秒

这是个很严重的问题,进行Major GC的时候程序会暂停,无法响应,居然会暂停5秒多,这谁都无法接受吧 :)

同样Minor GC进行了7647次,总用时1221.782 平均时间为0.16秒,算是可以接受

再来看看修改配置后:

jmap -heap 14103

Attaching to process ID 14103, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 11.0-b16

using parallel threads in the new generation.

using thread-local object allocation.

Concurrent Mark-Sweep GC

Heap Configuration:

   MinHeapFreeRatio = 40

   MaxHeapFreeRatio = 70

   MaxHeapSize      = 4294967296 (4096.0MB)

   NewSize          = 536870912 (512.0MB)

   MaxNewSize       = 536870912 (512.0MB)

   OldSize          = 5439488 (5.1875MB)

   NewRatio         =4                         YG:OG          1:4       

   SurvivorRatio    = 8

   PermSize         = 268435456 (256.0MB)

   MaxPermSize      = 268435456 (256.0MB)

Heap Usage:

New Generation (Eden + 1 Survivor Space):

   capacity = 483196928 (460.8125MB)

   used     = 428284392 (408.4438247680664MB)

   free     = 54912536 (52.368675231933594MB)

   88.63557841162434% used

Eden Space:

   capacity = 429522944 (409.625MB)

   used     = 404788608 (386.0364990234375MB)

   free     = 24734336 (23.5885009765625MB)

   94.24144010337199% used

From Space:

   capacity = 53673984 (51.1875MB)

   used     = 23495784 (22.407325744628906MB)

   free     = 30178200 (28.780174255371094MB)

   43.77499534970238% used

To Space:

   capacity = 53673984 (51.1875MB)

   used     = 0 (0.0MB)

   free     = 53673984 (51.1875MB)

   0.0% used

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~YG 大小和使用状态

concurrent mark-sweep generation:

   capacity = 3758096384 (3584.0MB)

   used     = 1680041600 (1602.2125244140625MB)

   free     = 2078054784 (1981.7874755859375MB)

   44.70459052494594% used

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~OG 大小和使用状态

Perm Generation:

   capacity = 268435456 (256.0MB)

   used     = 128012184 (122.0819320678711MB)

   free     = 140423272 (133.9180679321289MB)

   47.688254714012146% used

在这个配置下,GC运行情况:

jstat -gcutil -h5 14103 4s 100

  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT  

 47.49   0.00  64.82  46.08  47.69  20822 2058.631    68   22.734 2081.365

  0.00  37.91  38.57  46.13  47.69  20823 2058.691    68   22.734 2081.425 这里发生了一次YG GC,也就是MinorGC,耗时0.06s

 46.69   0.00  15.19  46.18  47.69  20824 2058.776    68   22.734 2081.510

 46.69   0.00  74.59  46.18  47.69  20824 2058.776    68   22.734 2081.510

  0.00  40.29  19.95  46.24  47.69  20825 2058.848    68   22.734 2081.582

MajorGC平均时间:22.734/68=0.334秒(上面是5秒多吧)

MinorGC平均时间:2058.691/20823=0.099秒(比上面略少)

分享到:
评论

相关推荐

    JVM垃圾回收机制与GC性能调优

    JVM堆相关知识 为什么先说JVM堆? JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在...这些对象的建立方式就是那些new一类的操作,当对象无用后,是GC来负责这个无用的对象(地球人都知道)。

    JVM的垃圾回收机制详解和调优

    JVM的垃圾回收机制详解和调优,gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和...

    jvm知识点总览(类的加载机制+内存结构+GC算法 垃圾回收+GC分析 命令调优)

    jvm知识点总览(类的加载机制+内存结构+GC算法 垃圾回收+GC分析 命令调优);jvm知识点总览(类的加载机制+内存结构+GC算法 垃圾回收+GC分析 命令调优);jvm知识点总览(类的加载机制+内存结构+GC算法 垃圾回收+GC...

    jMM+JVM-GC COLLECTOR+调优.pptx

    一个PPT包含 java内存模型,class运行机制。 java jvm垃圾回收算法 java jvm gc常见垃圾回收算法分析 java jvm调优

    Java垃圾回收机制详解和调优

    gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。

    JVM内存管理及GC原理调优实战

    但是当有性能问题的时候该怎么去调优,该去关注什么呢?在去做这项工作前就必须去了解JVM是怎么去管理内存的,GC是怎么完成的。 二、标记算法 垃圾回收是对已经分配出去的但又不再使用的内存进行回收,以便能够再次...

    Tomcat JVM的参数调优

    详细讲述了JVM参数的调优方法和步骤.并描述了GC垃圾回收机制的瓶颈,以及出现内存溢出的原因。

    分享:JVM及其性能调优,欢迎交流

    1.怎么运行?编译装载执行机制 2.怎么配置?JVM内存分代 3.怎么配置?GC垃圾回收 4.怎么监测?JVM监测工具 5.怎么监测?Linux监测工具 6.怎么调优?内存调优

    JVM调优话术

    java基础知识关于jvm的知识点 JVM调优就是GC是什么,为什么要有GC? GC就是垃圾回收,java这种语言是动态分配内存大小的,并且依靠 垃圾回收机制来完成对分配内存空间的回收,从而来避免内存溢出的问题, 也在一定...

    Java进阶教程解密JVM视频教程

    * 在垃圾回收章节,不仅会介绍垃圾回收算法、分代垃圾回收机制,还会重点介绍 G1 垃圾回收器,辨析 Full GC 发生条件,jdk8以来对垃圾回收的优化,以及垃圾回收的调优法则。 * 在字节码与类加载技术章节,会从一个 ...

    GC调优在Spark应用中的实践

    摘要:Spark立足内存计算,常常需要在内存中存放大量...由于Spark立足于内存计算,常常需要在内存中存放大量数据,因此也更依赖JVM的垃圾回收机制(GC)。并且同时,它也支持兼容批处理和流式处理,对于程序吞吐量和

    JVM内存调优深入文章共享

    最近总结JVM内存调优的一些东西,基本上是网上一些资料的汇总。 文章从算法,垃圾回收机制等多个方面对JVM的工作机制进行描述,使读者对JVM 有个全面的了解。

    浅谈jvm原理

    浅谈jvm原理(概念,运行机制,基本架构,运行时数据区,类加载系统,垃圾回收算法,垃圾回收策略,gc参数,调优策略)

    resin-jvm 调优

    2.几种垃圾回收机制 2.1.标记-清除收集器 这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。 2.2.标记-压缩收集器 ...

    JVM-Java虚拟机

    能学到什么:1,JVM底层运行机制和原理;2JVM参数;3,垃圾回收原理;4,垃圾回收器的使用;5,调优实战案例 导语:平时我们所说的JVM广义上指的是一种规范。狭义上的是JDK中的JVM虚拟机。JVM的实现是由各个厂商来做...

    初步理解:jvm运行机制,java程序运行机制,堆栈详解,jvm调优的目的。

    谷咕咕最近在准备面试,本来想多看看堆和栈的关系,看看发现又设计到gc(Garbage Collection)垃圾回收机制,发现盲区太多了,就去粗略的学习了一下jvm(java虚拟机),发现之前只会写程序,底层的东西真是太丰富了...

    高级开发jvm面试题和答案.pdf

    垃圾回收gc gc的标记方法; java对象的三种状态 gc算法; gc种类: 简述一下内存溢出的原因,如何排查线上问题? 内存溢出的原因 引用在gc中回收状况 为什么gc停止所有进程; 有几种垃圾回收器; 描述一下CMS和G1的...

    成为JavaGC专家上(2)—深入浅出Java垃圾回收机制

    GC监控是为了鉴别JVM是否在高效地执行GC,以及是否有必要进行额外的性能调优。基于以上信息,我们可以修改应用程序或者调整GC算法(GC优化)。有很多种方法可以监控GC,但其差别仅仅是GC操作通过何种方式展现而已。...

Global site tag (gtag.js) - Google Analytics