性能文章>一次java内存top res高排查记录>

一次java内存top res高排查记录原创

4周前
303600

前言

分享一个最近的问题,top 看java进程res不断升高,一天能涨3个G,使用jmap dump内存快照后,dump下来的文件只有300多M,没有发现内存泄漏。这是个什么情况呢,我们深入分析下。

冰山一角

首先,使用top来查看下当前进程的信息

请添加图片描述

可以看到top的res占用5.3g,jvm的参数如下

-Xmx8192M -Xms8192M -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDetails -XX:+PrintGCDateStamps -verbose:gc -Xloggc:/opt/ass/gc.log

早上的时候是4个g,下午的时候涨到7个g。

通过gc日志和gc次数和时间来看,fullgc并没有有效的清理掉内存。

我们使用jmap  -histo:live pid手动触发一次fullgc,发现res还在持续增长,也就是说内存肯定有泄漏的地方。

使用jmap dump出内存,查看泄漏的地方

jmap -dump:format=b,file=/opt/tmp/heapdump.hprof pid

dump下来发现,只有2个g,压缩后只有300M,分析内存中的数据,并没有泄漏的地方。

也就是说内存泄漏的地方可能在堆外。

分析堆外内存

NMT

NMT是Native Memory Tracking的缩写,是Java7U40引入的HotSpot新特性,开启后可以通过jcmd命令来对JVM内存使用情况进行跟踪。注意,根据Java官方文档,开启NMT会有5%-10%的性能损耗

-XX:NativeMemoryTracking=[off | summary | detail]  
# off: 默认关闭 
# summary: 只统计各个分类的内存使用情况.
# detail: Collect memory usage by individual call sites

添加-XX:NativeMemoryTracking=detail命令到启动参数中,然后重启项目。

执行

jcmd <pid> VM.native_memory summary scale=MB

由于我们使用的是jdk1.6,并不存在这个特性,所以只好用其他的办法。

ps

java -XX:+PrintFlagsFinal > flags.txt 可以看到当前java 支持所有xx的命令

pmap

pmap命令是Linux上用来开进程地址空间的

执行pmap -x | sort -n -k3 > pmap-sorted.txt命令可以根据实际内存排序

在这里插入图片描述

可以看到其他内存块占用的很少,最多的也只有60M,那也不可能是经典glibc的64M问题。

**pas+gdb

由于我们的不是内存地址段有问题,所以不dump出指定的范围的内存块。 如果是指定范围的内存块的话,可以这么操作

  • • 查看当前进程的所有地址cat /proc/pid/**aps > **pas.txt查看**aps.txt,找到有问题的内存块地址,比如下图中的 7fa956967000-7fa956a65000
在这里插入图片描述
  • • 启动gdbgdb attach <pid>
  • • dump指定范围的内存到指定的目录下,需要加0xdump memory /tmp/0x7fa956967000-0x7fa956a65000.dump 0x7fa956967000 0x7fa956a65000
  • • 显示长度超过10字符的字符串strings -10 /tmp/0x7fa956967000-0x7fa956a65000.dump
  • • dump 全部内存

由于我们这边内存都集中在一块,所以自己在业务低峰期,dump下了全部内存

  • • 设置ulimit  查看ulimit
    ulimit -a 
    core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 31722
    max locked memory       (kbytes, -l) 16384
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 65535
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 0
    stack size              (kbytes, -s) 8192
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 31722
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited
    为了导出core文件,需要先设置ulimitulimit -c unlimited
  • • dump内容gcore pid
  • • 显示长度超过10字符的字符串strings -10 core.pid > core.txt

查看内容后发现,内存中的数据是请求和响应的数据,查看代码后,怀疑是请求可能在某些情况下,没有正常的关闭。

在这里插入图片描述
分类:标签:
请先登录,感受更多精彩内容
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

不起眼,但是足以让你有收获的JVM内存分析案例
分析 这个问题说白了,就是说有些int[]对象不知道是哪里来的,于是我拿他的例子跑了跑,好像还真有这么回事。点该 dump 文件详情,查看相关的 int[] 数组,点该对象的“被引用对象”,发现所
从一起GC血案谈到反射原理
前言 首先回答一下提问者的问题。这主要是由于存在大量反射而产生的临时类加载器和 ASM 临时生成的类,这些类会被保留在 Metaspace,一旦 Metaspace 即将满的时候,就会触发 Fu
关于内存溢出,咱再聊点有意思的?
概述 上篇文章讲了JVM在GC上的一个设计缺陷,揪出一个导致GC慢慢变长的JVM设计缺陷,可能有不少人还是没怎么看明白的,今天准备讲的大家应该都很容易看明白 本文其实很犹豫写不写,因为感觉没有
协助美团kafka团队定位到的一个JVM Crash问题
概述 有挺长一段时间没写技术文章了,正好这两天美团kafka团队有位小伙伴加了我微信,然后咨询了一个JVM crash的问题,大家对crash的问题都比较无奈,因为没有现场,信息量不多,碰到这类问题我
又发现一个导致JVM物理内存消耗大的Bug(已提交Patch)
概述 最近我们公司在帮一个客户查一个JVM的问题(JDK1.8.0_191-b12),发现一个系统老是被OS Kill掉,是内存泄露导致的。在查的过程中,阴差阳错地发现了JVM另外的一个Bug。这个B
JVM实战:优化我的IDEA GC
IDEA是个好东西,可以说是地球上最好的Java开发工具,但是偶尔也会卡顿,仔细想想IDEA也是Java开发的,会不会和GC有关,于是就有了接下来对IDEA的GC进行调优 IDEA默认JVM参数: -
不起眼,但是足以让你收获的JVM内存案例
今天的这个案例我觉得应该会让你涨姿势吧,不管你对JVM有多熟悉,看到这篇文章,应该还是会有点小惊讶的,不过我觉得这个案例我分享出来,是想表达不管多么奇怪的现象请一定要追究下去,会让你慢慢变得强大起来,
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得