侧边栏壁纸
博主头像
再见理想博主等级

只争朝夕,不负韶华

  • 累计撰写 112 篇文章
  • 累计创建 64 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

记一次 java 进程占用内存过高分析

再见理想
2022-05-27 / 0 评论 / 0 点赞 / 372 阅读 / 801 字

一,发现服务器内存占用过高

巡检中发现服务器内存占用过高,接近 80%,进入服务器查看。

#按 k 查看
# free 

#按 m 查看
# free -m

total:总计物理内存的大小
used:已使用多大
free:可用有多少
Shared:多个进程共享的内存总额
Buffers/cached:磁盘缓存的大小
所以空闲内存 = free + buffers + cached = total - used


二,top

# top -c

#  然后shift + m 按照内存占用排序

可以看到,java 进程 19677 就占用了 24.7% ,8G 左右的内存。


三,查看该进程日志打印文件是否过大

进入该进程对应的服务目录,查看对应的日志打印文件是否过大而占用内存。

$ du -sh *

如果文件太大,置空该日志打印文件:

$ > xxx.log

四,定位线程问题

ps p {pid} -L -o pcpu,pmem,pid,tid,time,tname,cmd

可以看到进程 19677 产生了一百多个线程,一个线程默认占用 1m 空间。考虑是其它原因引起。

如果产生了太大的线程,成千过万,考虑是代码逻辑问题。

4.1,生成 dump 文件

# jmap -dump:format=b,file=dump.hprof {pid}

将 dump.hprof 导出本地,使用 Eclipse Memory Analyzer 进行分析线程和对象。


五,分析 Java 堆详细信息

可以用 jmap 命令查看 Java 堆详细信息,如使用哪种回收器,jvm 参数配置,分代情况等。

$  jmap -heap {pid}

可以看到,这个进程没有设置最大堆内存的信息,默认是服务器内存的 1/4。该进程实际使用的内存并不大,但整个进程占用了8G的内存。这种情况,可以考虑设置初始堆大小 -Xms 和最大堆大小 -Xmx 的值为适当的值。

5.1,分析堆中对象统计信息

如果空间占用率很大,用 jmap -histo 命令分析堆中对象统计信息,包括类、实例数量和合计容量等。

# jmap -histo:live {pid} > histo.log

# head -n 200 histo.log

知道了原因,对该服务的 -Xms 和 -Xmx 参数进行优化,重启该服务:

-Xms4g -Xmx4g

可以看到重启后该服务的内存占用降了下来,我们再用 jmap -heap {pid} 命令查看该服务的堆详细信息, -Xms 和 -Xmx 参数有无生效:


六,总结

内存占用过高问题,我们可以先用 top 命令定位占用内存过高的进程,排查该进程的日志打印文件是否过大而占用大量内存;排查该进程是否产生了大量的线程;通过查看对信息分析初始堆大小和最大堆大小的配置是否合理;进程的内存使用率是否过高,通过分析堆中对象统计信息或 dump 文件找出大对象,优化代码。

相关文章:

JDK的命令行工具
JVM系列三:JVM参数设置、分析

0

评论区