VisualVM 分析full GC问题记录
背景:JAVA APP,主要功能是处理日志并存入db
现象:运行一段时间就出现OOM问题,查看GC log发现运行没多久就一直Full GC,并且抛出OOM的异常。
[Full GC (Ergonomics) [PSYoungGen: 529920K->525999K(614912K)] [ParOldGen: 1398052K->1397869K(1398272K)] 1927972K->1923868K(2013184K), [Metaspace: 33827K->33827K(1079296K)], 4.1812153 secs] [Times: user=32.38 sys=0.07, real=4.19 secs]
[Full GC (Ergonomics) [PSYoungGen: 529920K->525483K(614912K)] [ParOldGen: 1397869K->1397848K(1398272K)] 1927789K->1923331K(2013184K), [Metaspace: 33832K->33832K(1079296K)], 5.6714054 secs] [Times: user=43.50 sys=0.09, real=5.67 secs]
GC日志中老年代非常大,而且回收效果也不明显。遇到这种问题,第一感觉还是有内存泄露,虽然Java能自己回收内存,但是不能保证我自己写的程序没有问题,比如曾经犯过一个错误往list一直add object,却没有remove,并且list也不释放,导致list越来越大,最后内存OOM。本着大胆假设,小心求证的理念,开始排查问题。
遇到内存问题,最好是希望能够直观的看到Java程序堆中现在有哪些对象,有哪些对象数目一直在递增而没有被回收。为此需要借助工具来排查了,visualVM是非常好的能满足需求的一个工具。
启动visualVM,启动程序,通过Visual GC查看内存情况。
从上图中,我们很明显发现程序的Old Generation占用空间是在不断地上涨,并且没有明显下跌,说明生成的对象都是存在内存里面的,并没有被释放掉。接下来查看一下内存中有哪些对象
使用Sampler标签页中的Memory 采集功能,查看内存中当前是哪些对象,从采样结果来看Request对象是非常多的,而且一直在递增。Request对象在程序中使用较多,接下来看下是哪个线程一直在积压Request
查看Per thread allocations,很容易看出insertRequestList线程分配的内存最多。
对照程序我恍然大悟,发现问题就出在插入数据上。程序中插入数据库采用异步批量插入方式,当生成一个Request对象就存入一个LinkedBlockingQueue,集满一定量进行批量插入。而我设置的LinkedBlockingQueue初始化了一个非常大的capacity,这就导致来不及插入的Request全部都堆积在LinkedBlockingQueue中了。
临时解决方案:将LinkedBlockingQueue的capacity设置小一些,并且采用put方式插入Request到LinkedBlockingQueue,当插入来不及的时候就等待。
修改代码后再来看下visualVM结果:
old Generation每次GC能回收大量的Object,不会出现Full GC了。
Request对象数量也并不是一直在增长了。但是InsertRequestThread线程仍然是分配了很多的内存,可以得知该线程必然还是积压了大量的Request对象的。因为只采用了临时解决方案,mysql插入数据速度上不去,积压在所难免。
附录:
visualVM远程监控
在执行Java 应用程序的服务器上先生成一个jstatd.all.policy
grant codebase "file:${JAVA_HOME}/lib/tools.jar" {
permission java.security.AllPermission;
};
然后执行命令
nohup ${JAVA_HOME}/bin/jstatd -J-Djava.rmi.server.hostname=10.111.123.234 -J-Djava.security.policy=jstatd.all.policy -J-Dcom.sun.management.jmxremote.authenticate=false -J-Dcom.sun.management.jmxremote.ssl=false -J-Dcom.sun.management.jmxremote.port=8888 &
然后在本地启动visualVM,Remote添加10.111.123.234,默认端口1099就可以监控服务器上的程序运行状况了,非常方便。
如果出现access denied ("java.util.PropertyPermission" "java.rmi.server.ignoreSubClasses" "write")报警,则建议将$JAVA_HOME和jstatd.all.policy都使用绝对路径。
VisualVM 分析full GC问题记录的更多相关文章
- JVM诊断及工具笔记(4) 使用visualvm分析JVM堆内存泄漏
在这里感谢最近一直阅读我文章的小伙伴,如果觉得文章对你有用,可以帮忙关注转载,需要的时候可以及时找到文章. 背景 今年Q3季度我们在推广业务方使用Iceberg,当时为了让不同业务线的用户可以使用自己 ...
- Java程序性能分析工具Java VisualVM(Visual GC)—程序员必备利器
VisualVM 是一款免费的\集成了多个JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优.这些功能包括生成和分析海量数据.跟踪内存泄漏.监控垃圾回收 ...
- 源码分析HotSpot GC过程(三):TenuredGeneration的GC过程
老年代TenuredGeneration所使用的垃圾回收算法是标记-压缩-清理算法.在回收阶段,将标记对象越过堆的空闲区移动到堆的另一端,所有被移动的对象的引用也会被更新指向新的位置.看起来像是把杂陈 ...
- VisualVM分析与HelloWorld、springBoot项目
VisualVM分析与HelloWorld.springBoot项目 自从1995年第一个JDK版本JDKBeta发布,至今已经快25年,这些年来Java的框架日新月异,从最开始的Servlet阶段, ...
- 源码分析HotSpot GC过程(一)
«上一篇:源码分析HotSpot GC过程(一)»下一篇:源码分析HotSpot GC过程(三):TenuredGeneration的GC过程 https://blogs.msdn.microsoft ...
- 使用Anemometer分析MySQL慢查询记录
数据库管理员一般是用percona的toolkit工具来分析MySQL慢查询记录,但是不够直观. 下面介绍一款比较直观的工具来统计分析MySQL慢查询记录anemometer. 在使用之前需要安装pe ...
- 使用VisualVM分析性能
性能分析神器VisualVM VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优.这些功能包括生成和分析海量 ...
- 基于binlog来分析mysql的行记录修改情况(python脚本分析)
最近写完mysql flashback,突然发现还有有这种使用场景:有些情况下,可能会统计在某个时间段内,MySQL修改了多少数据量?发生了多少事务?主要是哪些表格发生变动?变动的数量是怎 ...
- GC知识记录
2.关于Minor GC,Major GC与Full GC 1) Minor GC:即新生代的GC,指发生在新生代的垃圾收集动作.当新生代的Eden区内存不足时,就会触发Minor GC.由于对象创 ...
随机推荐
- 第二个MapReduce
大家在学习Hadoop的MapReduce的时候,90%的第一个程序都是WordCount,所以在这里分享一下我的第二个MapReduce程序.对于学习编程语言的人来说,有时候代码是最好的沟通方式之一 ...
- centos6.7安装openblas错误
centos系统:CentOS release 6.7 (Final)安装OpenBLAS # Install OpenBLAS at /usr/local/openblas git clone ht ...
- DES对称加密算法简析
1 对称加密算法 在了解DES算法前,先加单介绍一下对称加密算法,因为DES属于对称加密算法的一种. 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密 ...
- async await Task
一.使用Task 引用命名空间 using System.Threading.Tasks; 1.工厂方式 Task.Factory.StartNew(() => {Console.WriteLi ...
- Android 在通知栏实现计时功能
Notification是APP 向系统发出通知时,它将先以图标的形式显示在通知栏中.用户可以下拉通知栏查看通知的详细信息.我们可以在通知栏实现自定义的效果,也可以结合service和BroadCas ...
- jQuery与别的js框架冲突
jQuery.noConflict()运行这个函数将变量$的控制权让渡给第一个实现它的那个库. 这有助于确保jQuery不会与其他库的$对象发生冲突. <script type="te ...
- JavaScript(五):函数(闭包,eval)
1.函数的申明:三种方法: function命令 函数表达式:变量赋值 Function构造函数 //method 1: function命令 function test(){ console.log ...
- python_day05(去爬登录的豆瓣)
# 爬豆瓣需要用cookie# 需要注意隐藏的参数,即input 里面的默认的一些参数# 需要自己注册一个账户密码import urllib.requestimport http.cookiejarf ...
- openstack pike与ceph集成
openstack pike与ceph集成 Ceph luminous 安装配置 http://www.cnblogs.com/elvi/p/7897178.html openstack pike 集 ...
- codeforces 895B XK Segments 二分 思维
codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...