记录一次Java内存泄露分析过程
版权说明: 本文章版权归本人及博客园共同所有,转载请在文章前标明原文出处( https://www.cnblogs.com/mikevictor07/p/13032635.html ),以下内容为个人理解,仅供参考。
一、背景
最近在集成一个调用链客户端jaeger client(一种opentracing的实现)集成到自定义的SDK中,我们需要增加一种特性:能通过远端服务动态更新采样的参数。
按照jaeger的实现,如果关键参数(比如队列大小、buffer冲刷间隔等)的变动【必须重新建立一个比较重的Tracer】(可以理解为一个给上层调用的对象,无需了解细节),
按照多年的直觉(老油条),这个Tracer大对象的创建成本高,有泄露的可能。
二、使用方法
按照调用规范,我们的重建tracer这个对象后对旧的tracer进行close,源码如下:
/**
* Shuts down the {@link Reporter} and {@link Sampler}
*/
@Override
public void close() {
reporter.close();
sampler.close();
}
按理说调用close即可。
三、验证步骤
在这里使用了JProfiler来调试,启用应用后模拟每秒钟创建一次tracer,并且创建后关闭原先的tracer,然后通过JProfiler的Live Memory观察如下:
这里使用tracer这个关键词过滤信息快速找到相关对象,在点击上图的【Run GC】按钮后其他对象能回收,只有排名前两个对象无法进行回收,
说明它们存在强引用无法GC,而且数量一直在增长,右键第一行,选择【Show Select In Heap Walker】,如下:
选择进去后提示是否dump内存分析(若应用占用内存较大无法本地dump,可用memory analyzer tool继续dump hprof文件分析):
从references分析有哪些引用,结果如下:
从这里基本可以看出是JVM的shutdown hook强引用,我们再源码查找showdown hook的调用,结果如下:
if (builder.manualShutdown || runsInGlassFish()) {
log.info("No shutdown hook registered: Please call close() manually on application shutdown.");
} else {
// register this tracer with a shutdown hook, to flush the spans before the VM shuts down
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
JaegerTracer.this.close();
}
});
}
由于默认没有开启manual shutdown,jaeger为了应用停止时能close(内部主要是冲刷数据到agent)加了此特性。
四、修复与总结
修复方法很简单,将manual shutdown配置为true,并且自行实现关闭钩子即可(在我们的应用中是将tracer根据服务名put到map中,后一次对象将覆盖前一个,最后循环map关闭)。
本文章展示了使用jprofile来分析一次内存泄露的过程,如果对生产的memory分析,建议dump hprof文件到本地。
启动参数加上-XX:+HeapDumpOnOutOfMemoryError 以便保留当时内存快照,如果发生OOM后JVM杀掉触发OOM的线程,部分内存也被回收,事后分析的dump文件可能已经没有了原先到OOM的数据,只能等下一次发生,但有些情况几个月才发生一次,建议预先配置。
记录一次Java内存泄露分析过程的更多相关文章
- Java内存泄露分析和解决方案及Windows自带查看工具
Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身经历 ...
- JAVA内存泄露分析及解决
一,问题产生 项目采用Tomcat6.0为服务器,数据库为mysql5.1,数据库持久层为hibernate3.0,以springMVC3.0为框架,项目开发完成后,上线前夕进行稳定性拷机,测 ...
- 使用Eclipse Memory Analyzer 进行JAVA内存泄露分析
一,安装 Eclipse Memory Analyzer 在Memory Analyzer的官网找到 update site的地址:
- Java 内存泄露的理解与解决过程
本文详细地介绍了Java内存管理的原理,以及内存泄露产生的原因,同时提供了一些列解决Java内存泄露的方案,希望对各位Java开发者有所帮助. Java内存管理机制 在C++ 语言中,如果需要动态分配 ...
- java内存泄露的理解与解决(转)
Java内存管理机制 在C++语言中,如果需要动态分配一块内存,程序员需要负责这块内存的整个生命周期.从申请分配.到使用.再到最后的释放.这样的过程非常灵活,但是却十分繁琐,程序员很容易由于疏忽而忘记 ...
- 学会用Clang来进行内存泄露分析
最近项目出现了内存泄露的问题,对于PC x86平台来说,一点点的内存泄露往往不会出错,很难进行debug调试.这个时候我们可以用到苹果给我们带来的神器--Clang编译器来进行内存泄露分析检测,开关打 ...
- Java内存泄漏分析系列之五:常见的Thread Dump日志案例分析
原文地址:http://www.javatang.com 症状及解决方案 下面列出几种常见的症状即对应的解决方案: CPU占用率很高,响应很慢 按照<Java内存泄漏分析系列之一:使用jstac ...
- Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析
原文地址:http://www.javatang.com 一个典型的thread dump文件主要由一下几个部分组成: 上图将JVM上的线程堆栈信息和线程信息做了详细的拆解. 第一部分:Full th ...
- 关于java内存泄露的总结--引用的类型:强引用,弱引用,软引用
今天面试了一家公司的java开发方面的实习生,被问到一个问题:如何处理java中的内存泄露问题,保证java的虚拟机内存不会被爆掉,当时其实觉得面试官的问题有点泛,所以也没有很好领会他的意思,答案也不 ...
- Java内存泄露原因详解
一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的, 这些对象的创建都是在堆(He ...
随机推荐
- L2-030 冰岛人
需要注意的地方: 我们只记录维京人的祖先,除了维京人的其他人不能记录它的祖先 #include <bits/stdc++.h> using namespace std; struct pe ...
- python之继承及其实现方法
目录 继承 语法格式 继承的代码实现 多继承 继承 语法格式 class 子类类名(父类1, 父类2...): pass r如果一个类没有继承任何类,则默认继承object python支持多继承 定 ...
- Linux配置静态IP解决无法访问网络问题
Linux系统安装成功之后只是单机无网络状态,我们需要配置Linux静态IP来确保服务器可以正常连接互联网 1.首先安装ifconfig Centos7安装成功后,高版本会把ping命令给移除了,所以 ...
- Java 21 官方速览:全面拥抱虚拟线程
前言 首先,感谢一下不少xdm私信关心我的身体状况,我也不是什么厉害的大佬,点开通知看到一堆私信还是蛮感动的. 近来有意大幅缩短了更新频率,增加了日常调养身体的时间,淋巴结确实变小了,睡眠也逐渐正常, ...
- DataGtip的永久激活方法(Windows2021-2023版本均可)
一.打开DataGrip 出现以下界面即显示需要激活,否则无法使用,这里打开后点击Exit退出 二.下载激活包 1.下载激活包准备激活 下载链接: 链接:https://pan.baidu.com/s ...
- 7-8次PTA和期末成绩总结
(1)前言:总结之前所涉及到的知识点.题量.难度等情况 课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式(修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课 ...
- JTAG串链
- [ARC137E] Baker
Problem Statement Snuke runs a bakery. He is planning for the next $N$ days. Let us call these days ...
- [GDOIpj222A] 点指兵兵
第一题 点指兵兵 提交文件: bing.cpp 输入文件: bing.in 输出文件: bing.out 时间空间限制: 1 秒, 256 MB 你一定有过在两个物品之间犹豫不决的时候,想要借助一些方 ...
- linux环境下脚本部署项目出现nohup: redirecting stderr to stdout问题
解决办法: 把后面的 "&" 改成 "2>&1 &" 最终改为: nohup java -jar ${JAR_NAME} --lo ...