JVM(8)——GC的影响(总结)

1.基于JVM运行的系统最怕什么?

基于JVM运行的系统最害怕的问题:**系统卡顿问题!**就是每次一旦年轻代塞满之后,在进行垃圾回收的时候,这个期间都必须停止系统程序的运行!

2.年轻代gc到底多久一次对系统影响不大?

通常来说是不大的,假如说你的系统运行着,然后每隔几分钟或者几十分钟执行一次新生代gc,系统卡顿几十毫秒,就这期间的请求会卡顿几十毫秒,几乎用户都是无感知的,所以新生代gc一般基本对系统性能影响不大。

3.什么时候新生代gc对系统影响很大?

当你的系统部署在大内存机器上的时候,比如说你的机器是32核64G的机器,此时你分配给系统的内存有几十个G,新生代的Eden区可能30G~40G的内存。执行垃圾回收大概需要几秒钟,此时你发现,可能每过一分钟,你的系统就要卡顿几秒钟,有的请求一旦卡死几秒钟就会超时报错,此时可能会导致你的系统频繁出错。

4.如何解决大内存机器的新生代GC过慢的问题?

用G1垃圾回收器,G1基于他的Region内存划分原理,就可以在运行一段时间之后,比如就针对2G内存的Region进行垃圾回收,此时就仅仅停顿20ms,然后回收掉2G的内存空间,腾出来了部分内存,接着还可以继续让系统运行。G1天生就适合这种大内存机器的JVM运行,可以完美解决大内存垃圾回收时间过长的问题。

5.要命的频繁老年代gc问题

对象进入老年代的几个条件

  1. 对象年龄太大了,这种对象一般很少,都是系统中确实需要长期存在的核心组件,他们一般不需要被回收掉,所以在新生代熬过默认15次垃圾回收之后就会进入老年代。
  2. 动态年龄判定规则,如果一次新生代gc过后,发现Survivor区域中的几个年龄的对象加起来超过了Survivor区域的50%,比如说年龄1+年龄2+年龄3的对象大小总和,超过了Survivor区域的50%,此时就会把年龄3以上的对象都放入老年代。
  3. 新生代垃圾回收过后,存活对象太多了,无法放入 Surviovr中,此时直接进入老年代。

第二个和第三个都是很关键的,通常如果你的新生代中的Survivor区域内存过小,就会导致上述第二个和第三个条件频繁发生,然后导致大量对象快速进入老年代,进而频繁触发老年代的gc

老年代gc通常来说都很耗费时间,无论是CMS垃圾回收器还是G1垃圾回收器,因为比如说CMS就要经历初始标记、并发标记、重新标记、并发清理、碎片整理几个环节,过程非常的复杂,G1同样也是如此。

6.JVM性能优化到底在优化什么?

说白了,系统真正最大的问题,就是因为内存分配、参数设置不合理,导致你的对象频繁的进入老年代,然后频繁触发老年代gc,导致系统频繁的每隔几分钟就要卡死几秒钟。

7.gc概念
  1. Minor GC / Young GC,“新生代”也可以称之为“年轻代”,这两个名词是等价的。那么在年轻代中的Eden内存区域被占满之后,实际上就需要触发年轻代的gc,或者是新生代的gc。

  2. Old GC. 一直是说老年代一旦被占满之后,就会触发老年代的gc

  3. **Full GC ** Full GC指的是针对新生代、老年代、永久代的全体内存空间的垃圾回收,所以称之为Full GC。“Full”就是整体的意思,所以就是对JVM进行一次整体的垃圾回收,把各个内存区域的垃圾都回收掉。

  4. **Major GC ** 这个其实一般用的比较少,他也是一个非常容易混淆的概念

    有些人把Major GC跟Old GC等价起来,认为他就是针对老年代的GC,也有人把Major GC和Full GC等价起来,认为他是针对JVM全体内存区域的GC。

    所以针对这个容易混淆的概念,建议大家以后少提。如果听到有人说这个Major GC的概念,大家可以问清楚,他到底是想说Old GC呢?还是Full GC呢?

  5. Mixed GC 是G1中特有的概念,其实说白了,主要就是说在G1中,一旦老年代占据堆内存的45%了,就要触发Mixed GC,此时对年轻代和老年代都会进行回收

8.Young GC的触发时机

Young GC其实一般就是在新生代的Eden区域满了之后就会触发,采用复制算法来回收新生代的垃圾,

9.Old GC和Full GC的触发时机
  1. 发生Young GC之前进行检查,如果“老年代可用的连续内存空间” < “新生代历次Young GC后升入老年代的对象总和的平均大小”,说明本次Young GC后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间,此时必须先触发一次Old GC给老年代腾出更多的空间,然后再执行Young GC
  2. 执行Young GC之后有一批对象需要放入老年代,此时老年代就是没有足够的内存空间存放这些对象了,此时必须立即触发一次Old GC
  3. 老年代内存使用率超过了92%,也要直接触发Old GC,当然这个比例是可以通过参数调整的

一般Old GC很可能就是在Young GC之前触发或者在Young GC之后触发的,所以自然Old GC一般都会跟一次Young GC连带关联在一起了。

另外一个,在很多JVM的实现机制里,其实在上述几种条件达到的时候,他触发的实际上就是Full GC,这个Full GC会包含Young GC、Old GC和永久代的GC

也就是说触发Full GC的时候,可能就会去回收年轻代、老年代和永久代三个区域的垃圾对象。

10.永久代满了之后怎么办?

假如存放类信息、常量池的永久代满了之后,就会触发一次Full GC。Full GC有上述几个触发条件,同时触发Full GC的时候其实会带上针对新生代的Young GC,也会有针对老年代的Full GC,还会有针对永久代的GC。所以假如存放类信息、常量池的永久代满了之后,就会触发一次Full GC。

这样Full GC执行的时候,就会顺带把永久代中的垃圾给回收了,但是永久代中的垃圾一般是很少的,因为里面存放的都是一些类,还有常量池之类的东西,这些东西通常来说是不需要回收的。如果永久代真的放满了,回收之后发现没腾出来更多的地方,此时只能抛出内存不够的异常了

11Metaspace区域导致的full GC

频繁Full GC不光是老年代触发的,有时候也会因为Metaspace区域的类太多而触发。

在JVM启动参数中加入如下两个参数了:“-XX:TraceClassLoading -XX:TraceClassUnloading”,就是追踪类加载和类卸载的情况,他会通过日志打印出来JVM中加载了哪些类,卸载了哪些类。

12定位系统的大对象

jmap工具,通过后台jstat工具观察系统,什么时候发现老年代里突然进入了几百MB的大对象,就立马用jmap工具导出一份dump内存快照。

13内存分析工具
  1. 对线上系统导出一份内存快照
    jmap -dump:format=b,file=文件名 [服务进程ID]
  2. 拿到了内存快照之后,其实就是一份文件,接着就可以用jhat、MAT之类的工具来分析内存了
14内存泄漏

系统创建了大量的对象占用了内存,其实很多对象是不需要使用的,而且还无法回收掉。

15JVM和GC的运行原理

JVM的内存区域划分,最核心的就是这么几块了:年轻代、老年代、Metaspace(也就是以前的永久代)。其中年轻代又分成了Eden和2个Survivor,默认比例是8:1:1,随着Eden区不断的创建对象,就会逐步的塞满,当然这个时候可能塞满Eden区的对象里大多数都是垃圾对象。一旦Eden区塞满之后,就会触发一次Young GC。Young GC会采用复制算法,从GC Roots(方法的局部变量、类的静态变量)开始追踪,标记出来存活的对象。然后把存活对象都放入第一个Survivor区域中,也就是S0区域,接着垃圾回收器就会直接回收掉Eden区里剩余的全部垃圾对象,在整个这个垃圾回收的过程中全程会进入Stop the Wold状态,也就是暂停系统工作线程,系统代码全部停止运行,不允许创建新的对象,一旦垃圾回收全部完毕之后,也就是存活对象都进入了Survivor区域,然后Eden区都清空了,那么Young GC执行完毕,此时系统恢复工作,继续在Eden区里创建对象,下一次如果Eden区满了,就会再次触发Young GC,把Eden区和S0区里的存活对象转移到S1区里去,然后直接清空掉Eden区和S0区中的垃圾对象,负责Young GC的垃圾回收器有很多种,但是常用的就是ParNew垃圾回收器,他的核心执行原理就如上所述,只不过他运行的时候是基于多线程并发执行垃圾回收的,

16对象什么时候进入老年代?
  1. 一个对象在年轻代里躲过15次垃圾回收,
  2. 对象太大了,超过了一定的阈值,直接进入老年代,不走年轻代
  3. 一次Young GC过后存活对象太多了,导致Survivor区域放不下了,这批对象会进入老年代
  4. 动态年龄判定规则
17老年代的GC是如何触发的?
  1. 老年代自身可以设置一个阈值,有一个JVM参数可以控制,一旦老年代内存使用达到这个阈值,就会触发Full GC,一般建议调节大一些,比如92%
  2. 在执行Young GC之前,如果判断发现老年代可用空间小于了历次Young GC后升入老年代的平均对象大小的话,那么就会在Young GC之前触发Full GC,先回收掉老年代一批对象,然后再执行Young GC。
  3. 如果Young GC过后的存活对象太多,Survivor区域放不下,就要放入老年代,要是此时老年代也放不下,就会触发Full GC,回收老年代一批对象,再把这些年轻代的存活对象放入老年代中

总结起来,其实就是老年代一旦快要搞满了,空间不够了,必然要垃圾回收一次。Old GC的速度是很慢的,少则几百毫秒,多则几秒。所以一旦Full GC很频繁,就会导致系统性能很差,因为频繁要停止系统工作线程,导致系统看起来一直有卡顿的现象。,而且频繁Full GC还会导致机器CPU负载过高,导致机器性能下降,处理请求能力降低。

18线上频繁Full GC的几种表现
  • 机器CPU负载过高;
  • 频繁Full GC报警;
  • 系统无法处理请求或者处理过慢
19频繁Full GC的几种常见原因
  1. 系统承载高并发请求,或者处理数据量过大,导致Young GC很频繁,而且每次Young GC过后存活对象太多,内存分配不合理,Survivor区域过小,导致对象频繁进入老年代,频繁触发Full GC
  2. 系统一次性加载过多数据进内存,搞出来很多大对象,导致频繁有大对象进入老年代,必然频繁触发Full GC
  3. 系统发生了内存泄漏,莫名其妙创建大量的对象,始终无法回收,一直占用在老年代里,必然频繁触发Full GC
  4. Metaspace(永久代)因为加载类过多触发Full GC
  5. 误调用System.gc()触发Full GC

如果jstat分析发现Full GC原因是第一种,那么就合理分配内存,调大Survivor区域即可。

如果jstat分析发现是第二种或第三种原因,也就是老年代一直有大量对象无法回收掉,年轻代升入老年代的对象病不多,那么就dump出来内存快照,然后用MAT工具进行分析即可

如果jstat分析发现内存使用不多,还频繁触发Full GC,必然是第四种和第五种,此时对应的进行优化即可。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM中的年代垃圾回收是指对年代进行垃圾回收的过程。年代是堆内存的一部分,用于存放生命周期较长的对象。年代垃圾回收的触发条件与空间分配担保有关。在发生Minor GC之前,虚拟机会检查年代最大可用的连续空间是否大于新生代所有对象的总空间。如果大于,则此次Minor GC是安全的;如果小于,则虚拟机会根据HandlePromotionFailure设置值来决定是否进行空间分配担保。 空间分配担保是指在发生Minor GC时,如果年代的连续空间小于新生代所有对象的总空间,虚拟机会根据HandlePromotionFailure的设置值来决定后续的操作。如果HandlePromotionFailure为true,虚拟机会进一步检查年代最大可用连续空间是否大于历次晋升到年代的对象的平均大小。如果大于,则尝试进行一次Minor GC,但仍然有风险;如果小于或者HandlePromotionFailure为false,则会进行一次Full GC总结一下,年代垃圾回收是在发生Minor GC时对年代进行的垃圾回收过程。空间分配担保的目的是确保年代有足够的空间来容纳新生代的对象。如果空间不足,根据HandlePromotionFailure的设置值,虚拟机会决定是继续进行Minor GC还是进行一次Full GC。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [JVM垃圾回收——对象进入年代](https://blog.csdn.net/weixin_39555954/article/details/130042958)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值