`
lwt_cedric
  • 浏览: 115314 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

JVM垃圾回收机制与GC调整

    博客分类:
  • java
阅读更多
JVM垃圾回收机制与GC调整

一、GC概要:

JVM堆相关知识
    为什么先说JVM堆?
    JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象。这些对象的建立方式就是那些new一类的操作,当对象无用后,是GC来负责这个无用的对象(地球人都知道)。
JVM堆
    (1) 新域:存储所有新成生的对象
    (2) 旧域:新域中的对象,经过了一定次数的GC循环后,被移入旧域
    (3)永久域:存储类和方法对象,从配置的角度看,这个域是独立的,不包括在JVM堆内。默认为4M。

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




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用来放新产生的对象,经过几次回收还
二、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秒(比上面略少)

  • 大小: 62.1 KB
分享到:
评论

相关推荐

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

    Java虚拟机(JVM)的垃圾回收(GC)机制是Java程序高效运行的关键部分,它自动管理内存,释放不再使用的对象以避免内存泄漏。本文主要探讨JVM堆内存的结构和GC的工作原理,以及如何进行性能调优。 JVM堆是Java应用...

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

    本文将深入探讨JVM的垃圾回收机制,并分享一些优化GC性能的有效策略。 首先,理解JVM内存模型至关重要。JVM内存分为堆(Heap)、栈(Stack)、方法区(Method Area)等几个区域。其中,堆是GC的主要工作区域,用于...

    jvm垃圾回收机制总结

    本文将深入探讨JVM的垃圾回收机制,包括其原理、类型以及在实际开发中的应用。 一、垃圾回收的原理 1. 对象引用计数:一种简单的垃圾回收策略,为每个对象分配一个引用计数器,当有引用指向该对象时,计数器加一,...

    JVM 垃圾回收(GC)

    理解JVM垃圾回收机制对于优化Java应用性能至关重要。 1. **垃圾回收的基本概念** - **对象生命周期**:在Java中,对象的生命周期包括创建、使用和销毁。当对象不再被引用时,就被认为是“垃圾”。 - **垃圾回收器...

    垃圾回收垃圾回收垃圾回收

    垃圾回收的参数调整是JVM调优的重要部分,包括设置堆大小、新生代与老年代的比例、选择合适的垃圾收集器等。通过合理的配置,可以优化应用程序的性能,避免因垃圾回收导致的系统响应慢或者频繁Full GC等问题。 总之...

    JVM垃圾回收器和内存分配策略.zip

    本篇文章将深入探讨JVM的垃圾回收机制以及内存分配策略。 首先,我们需要了解JVM的内存模型。在Java中,内存主要分为堆(Heap)和栈(Stack)。堆是所有对象实例的存储区域,而栈则用于存储方法调用时的局部变量。...

    java垃圾回收(gc)机制详解

    而在Java中,引入了垃圾回收机制,自动处理这些任务,简化了编程工作,也降低了因忘记释放内存而导致的错误。 二、垃圾回收的工作原理 GC通过识别“可达性分析”来决定哪些对象是“活”的,哪些是“死”的(不再被...

    jvm垃圾回收机制详解,学习过程,如有侵权请联系删除

    理解JVM的垃圾回收机制对于优化Java应用性能至关重要,开发者可以通过调整JVM参数,如设置新生代和老年代的比例,选择合适的垃圾收集器,以及使用不同类型的引用,来控制GC的行为,以适应不同场景的需求。...

    JVM内存管理和JVM垃圾回收

    本文将详细解析JVM内存结构以及垃圾回收机制。 首先,JVM内存主要分为四个区域: 1. **堆(Heap)**:这是Java应用程序中最大的内存区域,用于存储所有通过`new`关键字创建的对象实例。堆被进一步划分为新生代...

    JVM垃圾回收(GC)原理归纳.pdf

    以下是对JVM垃圾回收(GC)原理的详细阐述: 1. **引用计数**:一种简单但效率低下的算法,每个对象都有引用计数,当引用增加时计数加一,引用减少时减一。当计数为0时,对象被视为垃圾。然而,它不能处理循环引用...

    jvm垃圾回收调整.pdf

    本篇文章将深入解析JVM的垃圾回收机制,并针对Sun HotSpot 1.4.1版本的JVM,讨论如何调整堆内存的大小以优化GC性能。 首先,JVM的堆内存被划分为三个主要区域:新域(Young Generation)、旧域(Tenured Generation...

    03-VIP-JVM内存分配机制与垃圾回收算法1

    理解JVM的内存分配和垃圾回收机制对于优化Java应用性能至关重要。开发者需要关注对象的生命周期,合理分配内存,避免大对象的频繁创建,以及减少不必要的Full GC调用,从而提高应用程序的运行效率。同时,调整JVM的...

    JVM垃圾回收与调优详解1

    《JVM垃圾回收与调优详解1》 Java虚拟机(JVM)的内存管理和垃圾回收是其性能优化的关键环节。本文主要探讨JVM内存分配、对象回收的判断标准以及垃圾收集算法。 1. JVM内存分配与回收 在JVM中,内存分为新生代、...

    JVM垃圾回收,参数,强软弱虚,常见错误OOM,与微服务结合.docx

    "JVM垃圾回收、参数、强软弱虚、常见错误OOM、与微服务结合" JVM垃圾回收是Java虚拟机(JVM)中的一种机制,用于自动回收无效对象所占用的内存资源。垃圾回收机制可以防止内存溢出、提高系统性能和可靠性。 在C/...

    jvm_gc.rar_jvm_垃圾回收

    了解JVM内存模型和垃圾回收机制对于Java开发人员来说非常重要,可以帮助解决内存溢出、性能瓶颈等问题,提升程序的稳定性和效率。通过深入学习这些概念,可以更好地理解和控制Java程序在运行时的行为。

    JAVA垃圾回收机制

    Java垃圾回收机制(GC)是Java编程语言的关键特性,它自动管理内存,释放不再使用的对象,以防止内存泄漏。GC的运作方式主要有两种策略:引用计数和对象引用遍历。 引用计数是一种简单但不完美的方法。每个对象都有...

    JVM垃圾回收及监控优化1

    总之,理解JVM的内存管理和垃圾回收机制对于解决内存溢出问题、提升系统并发性能至关重要。开发者需要深入理解不同GC算法的原理和特点,结合实际应用需求,进行合理的配置和调优,确保应用稳定、高效地运行。

    jvm内存模型以及垃圾回收机制.rar

    Java虚拟机(JVM)是Java程序运行的基础,它的内存模型和垃圾回收机制对于理解Java程序的性能和稳定性至关重要。本文将深入探讨这两个关键概念。 首先,我们来了解JVM内存模型。在Java中,内存主要分为堆内存(Heap...

Global site tag (gtag.js) - Google Analytics