写在前面:

最近开始总结内存方面的东西,已经总结以前遇到的一些内存案例分享下,接下来还有几篇,然后是进程/线程相关的,逐渐形成我的知识体系树

如果你有兴趣,可以文章末尾的公众号二维码一起梳理这些信息。

OOM问题一般都是人工代码失误, 多数其实在review阶段应该可以排除,本文主要是想记录下内存快照排查OOM的一个过程 

场景: 系统的交互安全完全依赖各种加密做(做到了无session,完全WEB无状态,这个设计以后可讲下),故加密变得很重要,但因为有新的加密引入了BouncyCastleProvider。故有修改,测试机一台机器上线一段时间后,运行一段时间后,系统变得非常缓慢,并到最后出现了OOM,最终产生内存快照文件。

分析:

JVM内存分析:观察JVM内存,发现大量OU被使用无法释放引起频发GC,导致系统缓慢(基本不可用)

内存快照分析OOM的原因, 对于这种内存分析最好的方法是dump两份,一份正常的,一份是发生OOM时候的进行对比

故障重现:

首先给1G内存给Tomcat,  当OOM时输出日志, JVM参数相关配置 如下:

 -Xms1024m -Xmx1024m -Xmn512m -XX:PermSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/log/dump/ 

正常启动后,先dump份正常的用于后面对比分析(拿OOM后产生的快照和正常的快照进行对比可以很方便找出泄漏的对象)

文件导入Eclipse Memory Analyzer

发现基本是Finalizer占用了内存

说明:JAVA创建对象时,会新建一个额外的Finalizer 对象指向新创建的对象。 而回收时,至少需要经过两次GC,所以这个是正常的一个内存

然后开始压测,2000次请求后,系统后面发现越来越慢,基本不可用了,查看GC,发现基本所有内存都满了,一直在GC

继续说快照, 此时再把内存dump下来导入,对比

打开快照,从全局图查看已经很明显能找到问题,内存都被JceSecurity占用了861M,可以确定是JceSecurity的问题。

进一步分析,一般用到下面3个报表

1, 查看全局内存

2, 内存泄漏分析

3, 大对象排序

这里直接用第2个,查看泄漏分析报告

96%的内存被JceSecurity这个类占用了

发现问题对象后,查看Details

显示这个类的基本情况,

是通过GC是ROOT追溯的最短路径,这个可以追溯到问题代码的类树的结构,并找到最终引用的代码中

可以最终找到直接引用类, 这里最终存在类 javax.crypto.jceSecurity的变量, verificationResults里面

2, 查看verificationResults里的内容

说明:

with outgoning references  查看它引用了哪些内容,可以看成是 集合包含了哪些内容

with incomming references 查看引用它的类

说明:

Shallow heap   是对象的自身占用大小

Retained Heap 是对象包含内容的的总大小

发现内存基本被它里面的一个BouncyCastleProvider占用。

最后根据快照能得出 : 

导致问题的地方在,类javax.crypto.jceSecurity的变量verificationResults里存的org.bouncycastle.jce.provider.BouncyCastleProvider

代码寻找:

根据上面找到代码中有用到org.bouncycastle.jce.provider.BouncyCastleProvider的地方,发现项目中的类CryptoUtil

工具类提炼出来;

关键是这句,每次都new了个BouncyCastleProvider

Cipher cipher = Cipher.getInstance(Constants.CRYPOTO_NAME, new BouncyCastleProvider());

这个类,代码来自7u40-b43

从 cipher.init进去

这段用于验证提供安全的provider对象是否是JCE可以信任的JAR,并把缓存结果存起来,将把该种provider当key存入一个静态的MAP中缓存起来, 故可以理解一到OLD区也未回收.

verificationResults的验证

值得说明的是,如果这里是HashMap而不是IdentivHashMap的话也是不会内存泄漏的,为什么这样说呢?

如果它这用的是HashMap, 不如new多少个BouncyCastleProvider, 在HashMap中也是一个,代码证实下:

/**
 * 小测试,用于说明下Provider与IdentityHashMap的分别特殊处理
 * @author 包子(何锦彬) 2017.01.20
 *
 */
public class Test {
    public static void main(String[] args) {
        Map hashMap=new HashMap();
        hashMap.put( new BouncyCastleProvider(), "provoder1");
        hashMap.put( new BouncyCastleProvider(), "provoder2");
        System.out.println(hashMap.size()); //输出是1

        Map identityMap=new IdentityHashMap();
        identityMap.put( new BouncyCastleProvider(), "provoder1");
        identityMap.put( new BouncyCastleProvider(), "provoder2");
        System.out.println(identityMap.size()); //输出是2

    }
}

原因如下:

1, java.security.Provider的hashCode和equals方法是有做特殊处理的,在provider中,只要密钥相等,两个Provider的比较是相等的

2,IdentivHashMap这个类和HashMap的主要区别是,PUT时判断两个KEY是否相等用的是==

IdentivHashMap代码如下:

而HashMap的这里是:

HashMap 里用的是 if (e.hash == hash && ((k = e.key) == key || key.equals(k))),比较的是hashCode与equals

解决

1.其实只要把指定方式由

Cipher cipher = Cipher.getInstance(Constants.CRYPOTO_NAME, new BouncyCastleProvider());

改成

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

2, 把BouncyCastleProvider改成单例模式

问1:

至于为什么要要指定用BouncyCastleProvider

http://blog.csdn.net/defonds/article/details/42775183

就OK,或者直接删除不指定

问2:

其实还可以打印下存活对象, jmap -histo 7276 > dump.txt, 已经能看出些端倪

持续更新留言问题,解答疑问

欢迎关注我的公众号,重现线上各种BUG, 一起来构建我们的知识体系

或搜 “包子的实验室”

 
 

内存快照排查OOM,加密时错误方法指定provider方式错误引起的OOM的更多相关文章

  1. JVM在遇到OOM(OutOfMemoryError)时生成Dump文件

    方法一: 命令:jmap -dump:format=b,file=heap.bin file:保存路径及文件名pid:进程编号(windows通过任务管理器查看,linux通过ps aux查看) du ...

  2. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  3. 嵌入式开发之内核内存异常排查---关闭oom killer

    通过执行以下命令,可以在1分钟内对系统资源使用情况有个大致的了解.uptimedmesg | tailvmstat 1mpstat -P ALL 1pidstat 1iostat -xz 1free ...

  4. Chrome JS内存泄漏排查方法(Chrome Profiles)

     原文网址:http://blog.csdn.net/kaitiren/article/details/19974269 JS内存泄漏排查方法(Chrome Profiles)   Google Ch ...

  5. JS内存泄漏排查方法——Chrome Profiles

    一.概述 Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是其中一个.Heap Profiling可以记录当前的堆内存(heap)快照,并生成对象的描述文件 ...

  6. JS内存泄漏排查方法-Chrome Profiles

    原文链接:http://caibaojian.com/chrome-profiles.html 一.概述 Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是 ...

  7. [转]JS内存泄漏排查方法(Chrome Profiles)

    Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是其中一个.Heap Profiling可以记录当前的堆内存(heap)快照,并生成对象的描述文件,该描述文 ...

  8. 记一次在node.js中使用crypto的createCipheriv方法进行加密时所遇到的坑

    Node.js的crypto模块提供了一组包括对OpenSSL的哈希.HMAC.加密.解密.签名,以及验证等一整套功能的封装.具体的使用方法可以参考这篇文章中的描述:node.js_crypto模块. ...

  9. Netty堆外内存泄露排查与总结

    导读 Netty 是一个异步事件驱动的网络通信层框架,用于快速开发高可用高性能的服务端网络框架与客户端程序,它极大地简化了 TCP 和 UDP 套接字服务器等网络编程. Netty 底层基于 JDK ...

随机推荐

  1. ecstore中kvstore之mongodb

    mongodb安装 详细见 http://blog.csdn.net/motian06/article/details/17560067 mongodb扩展安装 详细见 http://blog.csd ...

  2. PAT (Advanced Level) 1029. Median (25)

    scanf读入居然会超时...用了一下输入挂才AC... #include<cstdio> #include<cstring> #include<cmath> #i ...

  3. bootstrap中的居左和居右

    1.pull-left和pull-right 2.text-left.text-center和text-right

  4. UIButton 关灯小实验

    // 写在继承于UIViewController的子类中:创建单视图默认有ViewController类 // 实现:点击任何一颗UIButton,它四周的以及它自身都被变成红色,再点击就会变成原来的 ...

  5. iOS开发——打包静态库与Framework

    最近老是需要做接口给别的客户,就顺便把打包的过程也写一下吧! 一.静态库 静态图里面只能是纯文件,里面不能再有第三方打包的静态库,也就是说,静态库不能打包静态库.这个用的比较多,一般自己公司写出来的东 ...

  6. (简单) POJ 2750 Potted Flower,环+线段树。

    Description The little cat takes over the management of a new park. There is a large circular statue ...

  7. Delphi中unicode转汉字函数(转)

    源:Delphi中unicode转汉字函数 近期用到这个函数,无奈没有找到 delphi 自带的,网上找了下 有类似的,没有现成的,我需要的是 支持 “\u4f00 ” 这种格式的,即前面带标准的 “ ...

  8. Spring自学教程-介绍、特点、框架(一)

    一.spring是什么,有什么用? 一句话:面向企业应用,使用javabean代替ejb的java应用或web开发. 侵入式的做法就是要求用户代码"知道"框架的代码,表现为用户代码 ...

  9. 必须熟悉的vim快捷键操作

    转载请表明出处http://www.dabu.info/?p=801 Vim/Vi 没有菜单,只有命令 Vim/Vi 工作模式介绍:插入模式 和  命令模式 是vi的两个基本模式.——插入模式 ,是用 ...

  10. STM32F103外部中断编程

    STM32F103外部中断编程   中断,顾名思义就是停下手头的活,去干另外一件急活,干完急活然后回来继续干手头的活. 单片机和人一样,有时候也有更急的程序需要执行,执行完之后再回来执行之前正在执行的 ...