1.问题一个springboot应用内存占用过高
2. Jvisualvm排查
-
打开Jvisualvm后发现本地没有相应名称的进程
-
jps 查看进程pid为4308
-
根据进程pid在Jvisualvm中选择相应的进程
-
发现堆空间占用过高
-
安装插件GC插件
-
选择可用插件
如果没有插件的话
检查最新版本
-
插件中心无法连接
-
配置插件中心
-
查看jdk版本
-
查询插件中心
https://visualvm.github.io/pluginscenters.html
找到对应的仓库地址40<101<121
-
把上一步中找到仓库地址配置在Jvisualvm
配置完成后可用插件就有内容了
-
选择visual GC插件安装
-
安装完成后重启可以看到虚拟机gc
发现我们老年代占用极大
-
-
查看内存快照
-
内存快照分析
红框的示例数都是大于10万的
-
导出内存快照
3. JProfiler分析
-
打开快照
-
使用选定对象char[]
-
选择传出引用
发现有大量的sql语句
-
选择合并的支配引用 GC根到对象
发现百分之73的实例都是来自ibatis的DefaultSqlSessionFactory
从图中可以看出,MySQLBO中的DefaultSqlSession占用了大量的内存,而DefaultSqlSession是从哪里来的呢,翻开MyBatis的源码,原来SqlSessionFactory获取一个session的时候,是来至于DefaultSqlSession,那导致内存泄露的原因基本上就找到了。修改就很好修改了,每次循环开始的时候openSession,完毕执行sqlSession.close()就可以了。
4. 总结
- 大量的字符串导致的内存占用,但在GC之后就会清除问题不大
- 字符串来源:
- 日志中有大量数据
- mybatis大量的sql语句(sqlSession导致的内存泄漏)
- 解决方案:
- 关闭日志/减少日志的打印(只打印关键日志)
- sqlSession.close()