thanks:https://m.oschina.net/u/123553

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

转载 JAVA gc垃圾回收机制的更多相关文章

  1. 面试官,不要再问我“Java GC垃圾回收机制”了

    Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...

  2. 乐字节Java|GC垃圾回收机制、package和import

    本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...

  3. Android内存优化3 了解java GC 垃圾回收机制1

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  4. Android内存优化5 了解java GC 垃圾回收机制3

    引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Andro ...

  5. JAVA gc垃圾回收机制

    一.GC概要   JVM堆相关知识     为什么先说JVM堆?     JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方 ...

  6. Java GC - 垃圾回收机制

    1.简介 对于Java developer来说,了解JVM GC工作原理能够帮助我们开发出更优秀的应用,同时在处理JVM瓶颈时能够更加自由.在最近一年的应用开发中能体会到这些知识带来的好处,并且让我们 ...

  7. java GC垃圾回收机制G1、CMS

    CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间.对于要求服务器响应速度的应用上,这种垃圾回收器非常适合.在启动JVM参数加上-XX:+UseConcMa ...

  8. Android内存优化4 了解java GC 垃圾回收机制2 GC执行finalize的过程

    1. finalize的作用 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize()与C++中的析构函数 ...

  9. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

随机推荐

  1. ESP32搭建4.esp32官方程序下载与串口读取

    上一篇写到esp-idf的整体环境搭建,本文主要讲讲如何将examples中的例子烧写到ESP32的flash中,以及如何通过linux串口进行调试. 一. Esp32程序下载 1.Ctrl+Alt+ ...

  2. Python中的传参是传值还是传址?

    传值:在C++中,传值就是把一个参数的值给这个函数,其中的更改不会影响原来的值. 传址:即传引用,直接把这个参数的内存地址传递进去,直接去这个内存地址上进行修改. 但是这些在Python中都没有,Py ...

  3. 小程序中input设置宽度后宽度还有空间,但是placeholder被遮挡问题

    最近在做小程序,已经设置了宽高,placeholder没有超出input宽度,却被挡住了一部分,上代码看一下: wxml: <view class='container'> <inp ...

  4. 断网环境,Python环境迁移

    Python刚装好断网了怎么办? wget不管用怎么办? 想把现有的Python环境转移到另外一台机器上怎么办? 这就用到了离线安装 1.创建目录用于存放下载的包,并进入该目录 mkdir lihai ...

  5. require的特点

    通过把要加载的文件看作一个“功能”而不是一个文件,require对于用Ruby编写的扩展和用C语言编写的扩展都用一样的方式.另外,.rb扩展名的文件与其它扩展名为.so..dll或.bundle的文件 ...

  6. jenkins git ftp 发布.net 项目

    一次搞这个,在其他文章的基础上 添加下自己的 笔记,方便自己查看, -------需要准备的东西--------------- 下载jenkins https://jenkins.io/downloa ...

  7. ./sample_mnist: error while loading shared libraries: libnvinfer.so.4: cannot open shared object file: No such file or directory

    Your library is a dynamic library. You need to tell the operating system where it can locate it at r ...

  8. mysql 按类别之用一条SQL语句查询出每个班前10名学生数据

    select * from 学生信息表 a where 10 >  (select count(*) from 学生信息表 where 班级ID = a.班级ID and 班内名次 > a ...

  9. soapui 测试 带hear 验证的写法

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web=& ...

  10. 为什么想起开通blog?

    为什么想起开通博客 2016年跨年夜写年终总结时,曾对自己许下愿,要成为一个会讲“故事”的人,无奈口才不行,写字也不好看,所以只能在电脑上码码字代替了. 在我看来,这“故事”该有许多种含义:首先,电子 ...