zoukankan      html  css  js  c++  java
  • 记录一次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的数据,只能等下一次发生,但有些情况几个月才发生一次,建议预先配置。

  • 相关阅读:
    修改maven远程仓库为阿里的maven仓库(复制)
    Vue下iframe如何实现和父窗口的通信
    Vue在子组件内如何触发父组件的方法
    PhpStorm环境设置Debug
    史上最全的Excel数据编辑处理技巧(转)
    按钮样式
    字符和数字对齐的字体
    使用jquery控制只能输入数字,并且关闭输入法(转)
    Javascript中字符串转换成Date的方法
    MongoDB工具MagicMongoDBTool
  • 原文地址:https://www.cnblogs.com/mikevictor07/p/13032635.html
Copyright © 2011-2022 走看看