zoukankan      html  css  js  c++  java
  • Java服务,内存OOM了,如何快速定位?

    原文:https://mp.weixin.qq.com/s/bClGUG32QQmdgtnpyo431Q

    某Java服务(假设PID=10765)出现了OOM,如何快速定位?

    Java服务出现OOM,最常见的原因是:

    (1)内存确实分配过小,内存确实不够用;

    (2)某一个对象被频繁申请,却没有释放,内存不断泄漏,导致内存耗尽;

    (3)某一个资源被频繁申请,系统资源耗尽,例如:不断创建线程,不断发起网络连接;

    更具体的,可以按照以下步骤,使用以下工具排查。

     一、确认是不是内存本身就分配过小

    方法:jmap -heap 10765

    如下图,可以查看新生代、老生代堆内存的分配大小以及使用情况,看是否本身分配过小。

     

     二、找到最耗内存的对象

     方法:jmap -histo:live 10765 | more

     如上图,输入命令后,会以表格的形式显示存活对象的信息,并按照所占内存大小排序:

    (1)实例数;

    (2)所占内存大小;

    (3)类名;

    是不是很直观?对于实例数较多,占用内存大小较多的实例/类,相关的代码就要针对性review了。

    画外音:需要说明的是,jmap -histo:live会执行一次FGC,如果仍无法定位,可dump内存,通过Java内存分析工具MAT(Memory Analyzer Tool线下进行分析。

    上图中占内存最多的对象是RingBufferLogEvent,共占用内存18M,属于正常使用范围。 

    如果发现某类对象占用内存很大(例如几个G),很可能是类对象创建太多,且一直未释放。

    例如:(1)申请完资源后,未调用close()或dispose()释放资源;

             (2)消费者消费速度慢(或停止消费了),而生产者不断往队列中投递任务,导致队列中任务累积过多;

    三、确认是否是资源耗尽

     工具:

    (1)pstree

    (2)netstat

    查看进程创建的线程数,以及网络连接数,如果资源耗尽,也可能出现OOM。 

    这里介绍另一种方法,通过

    (1)/proc/${PID}/fd

    (2)/proc/${PID}/task

    可以分别查看句柄详情和线程数。

     例如,某一台线上服务器的sshd进程PID是9339,

    执行:ll /proc/9339/fdll /proc/9339/task

    如上图,sshd共占用了四个句柄

    (1)0 -> 标准输入;

    (2)1 -> 标准输出;

    (3)2 -> 标准错误输出;

    (4)3 -> socket(容易想到是监听端口);

     sshd只有一个主线程PID为9339,并没有多线程。 

    所以,只要

    ll /proc/${PID}/fd | wc -lll /proc/${PID}/task | wc -l (效果等同pstree -p | wc -l)

    就能知道进程打开的句柄数和线程数。

     

  • 相关阅读:
    Spring MVC 核心组件详解
    Spring MVC 入门就这一篇
    Spring 事务解决方案
    【UGUI源码分析】Unity遮罩之Mask详细解读
    游戏开发中不同时区下的时间问题
    ARTS第十三周(阅读Tomcat源码)
    Win10 电脑安装.NET低版本提示“这台计算机中已经安装了 .NET Framwork 4.6.2或版本更高的更新”问题
    Dynamics 365 Setup 提示SqlServer 存在
    Dynamics CRM "Verification of prerequisites for Domain Controller promotion failed. Certificate Server is installed."
    Dynamics CRM
  • 原文地址:https://www.cnblogs.com/shay/p/13215685.html
Copyright © 2011-2022 走看看