文章目录
- 1、图一:正常情况
- 2、图二:缓存对象过多
- 3、图三:内存泄漏
- 4、图四:频繁持续Full GC
- 5、图五:元空间不足导致的Full GC
1、图一:正常情况
正常的堆内存如图:
- 锯齿状
- 对象创建后内存占用上升,Full GC后下降到和之前接近的位置
2、图二:缓存对象过多
特点:
- 锯齿状
- 对象创建后内存占用上升,Full GC后下降到和之前接近的位置
- 但每次下降后的位置,其值也较大
这说明程序中保存了大量的缓存对象,GC后无法回收。比如程序中一些缓存用的Map,类似Map --> Redis --> MySQL的递进关系,这种不算内存泄漏,因为它有在发挥作用。这种缓存多了也不尽都是好处,可用MAT找到缓存了哪些对象。
3、图三:内存泄漏
- 锯齿状
- 每次垃圾回收之后下降到的内存位置越来越高
4、图四:频繁持续Full GC
如此频繁Full GC,给用户的感觉就是系统变卡了、变慢了,这是因为吞吐降低了(大量的时间用在了Full GC上,而不是用在了处理用户请求上)
大量的对象在内存中创建,同时JVM不停的Full GC在释放内存,可以看到内存有一定的下降(如下图中我黄色圈圈起来的白色三角),但很快就被新创建的对象又占满了
【相关的GcEasy报告】
从对象数据中也可以得到验证:每秒能产生198.76M大小的对象,晋升到老年代的也有65.85M数据,可见对象创建的确实很快
再看下面引起GC的原因,前两个是:
- Ergonomics:垃圾回收器会根据自己的需要,比如保持一个较高的吞吐量或者比较短的STW,而触发的GC
- Allocation Failure:对象在分配到年轻代或者老年代的时候,空间不足了,导致了GC。此原因引起的GC占了45次。
⇒ 对象产生速度过快,而堆空间较小,导致了频繁的Full GC,进而影响到了客户请求的响应时间
5、图五:元空间不足导致的Full GC
特点:堆内存处于比较低的状态,但却频繁发生Full GC
【相关的GcEasy报告】
相关报告分析:
再看GC原因:将近5000次是因为元空间的大小达到了阈值(Metadata GC Threshold)
但发现这里JVM给元空间分配了1.2G,占用了652M,似乎没有到元空间阈值,这是JVM会动态的去计算元空间的阈值,只要元空间大小超过了这个阈值,就会触发Full GC,而这里的652可能已经多次超过了这个动态阈值