Java性能优化之JVM GC(垃圾回收机制)

Java的性能优化,整理出一篇文章,供以后温故知新。

这里写图片描述

在学习Java GC 之前,我们需要记住一个单词:stop-the-world 。它会在任何一种GC算法中发生。stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行。当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成。GC优化很多时候就是减少stop-the-world 的发生。

这里写图片描述

需要注意的是,JVM GC只回收堆区和方法区内的对象。而栈区的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。

这里写图片描述

  • 对象没有引用

  • 作用域发生未捕获异常

  • 程序在作用域正常执行完毕

  • 程序执行了System.exit()

  • 程序发生意外终止(被杀线程等)

在Java程序中不能显式的分配和注销缓存,因为这些事情JVM都帮我们做了,那就是GC。

有些时候我们可以将相关的对象设置成null 来试图显示的清除缓存,但是并不是设置为null 就会一定被标记为可回收,有可能会发生逃逸。

将对象设置成null 至少没有什么坏处,但是使用 System.gc() 便不可取了,使用 System.gc() 时候并不是马上执行GC操作,而是会等待一段时间,甚至不执行,而且 System.gc() 如果被执行,会触发 Full GC ,这非常影响性能。

这里写图片描述

eden区空间不够存放新对象的时候,执行 Minro GC。升到老年代的对象大于老年代剩余空间的时候执行 Full GC,或者小于的时候被HandlePromotionFailure 参数强制 Full GC 。调优主要是减少 Full GC的触发次数,可以通过 NewRatio 控制新生代转老年代的比例,通过MaxTenuringThreshold 设置对象进入老年代的年龄阀值(后面会介绍到)。

这里写图片描述

新生代(Young generation):绝大多数最新被创建的对象都会被分配到这里,由于大部分在创建后很快变得不可达,很多对象被创建在新生代,然后“消失”。对象从这个区域“消失”的过程我们称之为: Minro GC

老年代(Old generation):对象没有变得不可达,并且从新生代周期中存活了下来,会被拷贝到这里。其区域分配的空间要比新生代多。也正由于其相对大的空间,发生在老年代的GC次数要比新生代少得多。对象从老年代中消失的过程,称之为: Minro GC 或者 Full GC

**持久代(Permanent generation)**也称之为 方法区(Method area):用于保存类常量以及字符串常量。注意,这个区域不是用于存储那些从老年代存活下来的对象,这个区域也可能发生GC。发生在这个区域的GC事件也被算为 Major GC 。只不过在这个区域发生GC的条件非常严苛,必须符合以下三种条件才会被回收:

这里写图片描述

代码交流 2021