一次问题排查引发的MemoryAnalyzer使用分析内存

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a303549861/article/details/82887431

一次问题排查,错误信息:
日志,框架是 dubbo springboot data jpa

Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Could not open connection
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387) ~[hibernate-entitymanager-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310) ~[hibernate-entitymanager-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1397) ~[hibernate-entitymanager-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:62) ~[hibernate-entitymanager-4.2.12.Final.jar!/:4.2.12.Final]
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:170) ~[spring-orm-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
	at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) ~[spring-orm-4.2.4.RELEASE.jar!/:4.2.4.RELEASE]
	... 39 common frames omitted
Caused by: org.hibernate.exception.GenericJDBCException: Could not open connection
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:124) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:221) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1351) ~[hibernate-core-4.2.12.Final.jar!/:4.2.12.Final]
	at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:59) ~[hibernate-entitymanager-4.2.12.Final.jar!/:4.2.12.Final]
	... 41 common frames omitted
Caused by: com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 60058, active 22, maxActive 200
	at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1139) ~[druid-1.0.15.jar!/:1.0.15]
	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:960) ~[druid-1.0.15.jar!/:1.0.15]
	at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4544) ~[druid-1.0.15.jar!/:1.0.15]
	at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:662) ~[druid-1.0.15.jar!/:1.0.15]
	at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4540) ~[druid-1.0.15.jar!/:1.0.15]
	at com.alibaba.druid.filter.FilterAdapter.dataSource_getConnection(FilterAdapter.java:2723) ~[druid-1.0.15.jar!/:1.0.15]
	at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4540) ~[druid-1.0.15.jar!/:1.0.15]

同时发现内存已经满了,抛出来OOM

java.lang.OutOfMemoryError: Java heap space: failed reallocation of scalar replaced objects

会使用工具的直接往下看解决办法,不会使用的耐心看。

1.简介

MAT是一个eclipse的插件,上手起来比较快。它能够快速的分析dump文件,可以直观的看到各个对象在内存占用的量大小,以及类实例的数量,对象之间的引用关系,找出对象的GC Roots相关的信息,此外还能生成内存泄露报表,疑似泄露大对象的报表等等。

2.使用方法

2.1 下载

下载地址:https://pan.baidu.com/s/1LxyFf6LfY1BBBXhMbMeSug

2.2 使用方法

1.如何获取Heap Dump
打开欢迎页点击How to Get a Heap Dump
在这里插入图片描述
进入获取dump页面,可以看到获取方法:

  • 方法一: jmap -dump:format=b,file=xxx.bin ${pid}
    在这里插入图片描述
  • 方法二:File-》Acquire Heap Dump -》选择要dump的java进程-》finish
    在这里插入图片描述
    2.如何分析
    生成完dump后,可以用MAT打开 dump(如果是MAT dump完后会自动进行解析),File-》Open Heap Dump 对dump文件进行解析,最终生成一个Overview视图,这个图是一个概要图,显示了一些统计信息,包括整个size大小,class数量,以及对象 的数量,同时还将生成一个大对象的top图,并线显示大对象占用内存的百分比。
    比如:Size: 2.9 GB Classes: 21.3k Objects: 30.3m Class Loader: 327 Unreachable Objects Histogram
    在这里插入图片描述
    开始分析:
    1)查找溢出源
    第一先看Histogram视图(截图里柱子那个,边上的是Dominator Tree ):列出每個class产生了多少個实例,以及占有多大内存,所占百分比。
    在这里插入图片描述
    可以很容易找出站内存最多的几个类,根据Retained Heap排序,找出前几个。
    可以分不同的维度来查看类的Histogram视图,Group by class、Group by superclass、Group by class loader、Group by package
    只要有溢出,时间久了,溢出类的实例数量或者其占有的内存会越来越多,排名也就越来越前,通过多次对比不同时间点下的Histogram图对比就能很容易把溢出类找出来。
    在这里插入图片描述
    如果发现不了问题,第二看Dominator Tree(支配树):列出每个对象(Object instance)与其引用关系的树状结构,还包含了占有多大内存,所占百分比。
  • 可以很容易的找出占用内存最多的几个对象,根据Percentage(百分比)来排序。
  • 可以分不同维度来查看对象的Dominator Tree视图,Group by class、Group by class loader、Group by package
  • 和Histogram类似,时间久了,通过多次对比也可以把溢出对象找出来,Dominator Tree和Histogram的区别是站的角度不一样,Histogram是站在类的角度上去看,Dominator Tree是站的对象实例的角度上看,Dominator Tree可以更方便的看出其引用关系。
    在这里插入图片描述
    通 过Histogram视图或者Dominator Tree视图,找到疑似溢出的对象或者类后,选择Path to GC Roots或者Merge Shortest Paths to GC Roots,这里有很多过滤选项,一般来讲可以选择exclude all plantom/weak/soft etc. references。这样就排除了虚引用、弱引用、以及软引用,剩下的就是强引用。从GC上说,除了强引用外,其他的引用在JVM需要的情况下是都可以 被GC掉的,如果一个对象始终无法被GC,就是因为强引用的存在,从而导致在GC的过程中一直得不到回收,因此就内存溢出了。
    接下来就需要直接定位具体的代码,看看如何释放这些不该存在的对象,比如是否被cache住了,还是其他什么原因。
    找到原因,清理干净后,再对照之前的操作,看看对象是否还再持续增长,如果不在,那就说明这个溢出点被成功的堵住了。
    最后用jstat跟踪一段时间,看看Old和Perm区的内存是否最终稳定在一个范围内,如果长时间稳定在一个范围,那溢出的问题就解决了,如果还再继续增长,那继续用上述方法,看看是否存在其他代码的溢出点,继续找出,将其堵住。
    在这里插入图片描述
  • 此外通过list objects或show objects by class也可以达到类似的效果,不过没看GC
    Roots的方式直观,这里就不细说了。
  • list objects – with outgoing references : 查看这个对象持有的外部对象引用。
  • list objects – with incoming references :查看这个对象被哪些外部对象引用。
    show objects by class – with outgoing references:查看这个对象类型持有的外部对象引用
    show objects by class – with incoming references :查看这个对象类型被哪些外部对象引用

同时我们可以通过Inspector查看:
在这里插入图片描述
在这里插入图片描述
上面讲述了使用方法,开始检查我们的问题,其实很简单,按照步骤就找出问题:

问题发现:
在这里插入图片描述
查看内存最大的list,发现数量是:
Type|Name|Value

int |size|529252

然后发现主要是mysql查询的问题:
在这里插入图片描述

然后重点查看这几个项,主要是第二项,马赛克就是我们要找的问题类:
在这里插入图片描述
问题定位,发现是有全表扫描问题,参数为空,然后看代码解决bug就好了:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/a303549861/article/details/82887431