JAVA进程占用高内存原因分析与优化方法

   首先看一下一个java进程的jmap输出:

 代码如下  

[lex@chou ~]$ jmap -heap 837
Attaching to process ID 837, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.10-b01

using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 4294967296 (4096.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 41025536 (39.125MB)
   used     = 18413552 (17.560531616210938MB)
   free     = 22611984 (21.564468383789062MB)
   44.883147900858624% used
From Space:
   capacity = 4325376 (4.125MB)
   used     = 3702784 (3.53125MB)
   free     = 622592 (0.59375MB)
   85.60606060606061% used
To Space:
   capacity = 4521984 (4.3125MB)
   used     = 0 (0.0MB)
   free     = 4521984 (4.3125MB)
   0.0% used
PS Old Generation
   capacity = 539820032 (514.8125MB)
   used     = 108786168 (103.74657440185547MB)
   free     = 431033864 (411.06592559814453MB)
   20.152302906758376% used
PS Perm Generation
   capacity = 85983232 (82.0MB)
   used     = 60770232 (57.95500946044922MB)
   free     = 25213000 (24.04499053955078MB)
   70.67684080542588% used

  然后再用ps看看:

 代码如下  
[lex@chou ~]$ ps -p 837 -o vsz,rss
   VSZ   RSS
7794992 3047320

  关于这里的几个generation网上资料一大把就不细说了,这里算一下求和可以得知前者总共给Java环境分配了644M的内存,而ps输出的VSZ和RSS分别是7.4G和2.9G,这到底是怎么回事呢?

  前面jmap输出的内容里,MaxHeapSize 是在命令行上配的,-Xmx4096m,这个java程序可以用到的最大堆内存。

  VSZ是指已分配的线性空间大小,这个大小通常并不等于程序实际用到的内存大小,产生这个的可能性很多,比如内存映射,共享的动态库,或者向系统申请了更多的堆,都会扩展线性空间大小,要查看一个进程有哪些内存映射,可以使用 pmap 命令来查看:

 代码如下  
[lex@chou ~]$ pmap -x 837
837:   java
Address           Kbytes     RSS   Dirty Mode   Mapping
0000000040000000      36       4       0 r-x--  java
0000000040108000       8       8       8 rwx--  java
00000000418c9000   13676   13676   13676 rwx--    [ anon ]
00000006fae00000   83968   83968   83968 rwx--    [ anon ]
0000000700000000  527168  451636  451636 rwx--    [ anon ]
00000007202d0000  127040       0       0 -----    [ anon ]
...
...
00007f55ee124000       4       4       0 r-xs-  az.png
00007fff017ff000       4       4       0 r-x--    [ anon ]
ffffffffff600000       4       0       0 r-x--    [ anon ]
----------------  ------  ------  ------
total kB         7796020 3037264 3023928

  这里可以看到很多anon,这些表示这块内存是由mmap分配的。

  RSZ是Resident Set Size,常驻内存大小,即进程实际占用的物理内存大小, 在现在这个例子当中,RSZ和实际堆内存占用差了2.3G,这2.3G的内存组成分别为:

  JVM本身需要的内存,包括其加载的第三方库以及这些库分配的内存

  NIO的DirectBuffer是分配的native memory

  内存映射文件,包括JVM加载的一些JAR和第三方库,以及程序内部用到的。上面 pmap 输出的内容里,有一些静态文件所占用的大小不在Java的heap里,因此作为一个Web服务器,赶紧把静态文件从这个Web服务器中人移开吧,放到nginx或者CDN里去吧。

  JIT, JVM会将Class编译成native代码,这些内存也不会少,如果使用了Spring的AOP,CGLIB会生成更多的类,JIT的内存开销也会随之变大,而且Class本身JVM的GC会将其放到Perm Generation里去,很难被回收掉,面对这种情况,应该让JVM使用ConcurrentMarkSweep GC,并启用这个GC的相关参数允许将不使用的class从Perm Generation中移除, 参数配置: -XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled,如果不需要移除而Perm Generation空间不够,可以加大一点: -X:PermSize=256M -X:MaxPermSize=512M

  JNI,一些JNI接口调用的native库也会分配一些内存,如果遇到JNI库的内存泄露,可以使用valgrind等内存泄露工具来检测

  线程栈,每个线程都会有自己的栈空间,如果线程一多,这个的开销就很明显了

  jmap/jstack 采样,频繁的采样也会增加内存占用,如果你有服务器健康监控,记得这个频率别太高,否则健康监控变成致病监控了。

  关于JVM的几个GC堆和GC的情况,可以用jstat来监控,例如监控进程837每隔1000毫秒刷新一次,输出20次:

 代码如下  
[lex@chou ~]$ jstat -gcutil 837 1000 20
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
  0.00  80.43  24.62  87.44  98.29   7101  119.652    40   19.719  139.371
  0.00  80.43  33.14  87.44  98.29   7101  119.652    40   19.719  139.371

  几个字段分别含义如下:

  S0

  年轻代中第一个survivor(幸存区)已使用的占当前容量百分比

  S1

  年轻代中第二个survivor(幸存区)已使用的占当前容量百分比

  E

  年轻代中Eden(伊甸园)已使用的占当前容量百分比

  O

  old代已使用的占当前容量百分比

  P

  perm代已使用的占当前容量百分比

  YGC

  从应用程序启动到采样时年轻代中gc次数

  YGCT

  从应用程序启动到采样时年轻代中gc所用时间(s)

  FGC

  从应用程序启动到采样时old代(全gc)gc次数

  FGCT

  从应用程序启动到采样时old代(全gc)gc所用时间(s)

  GCT

  从应用程序启动到采样时gc用的总时间(s)

  结论

  因此如果正常情况下jmap输出的内存占用远小于 RSZ,可以不用太担心,除非发生一些严重错误,比如PermGen空间满了导致OutOfMemoryError发生,或者RSZ太高导致引起系统公愤被OOM Killer给干掉,就得注意了,该加内存加内存,没钱买内存加交换空间,或者按上面列的组成部分逐一排除。

  这几个内存指标之间的关系是:VSZ >> RSZ >> Java程序实际使用的堆大小

时间: 2025-01-24 00:51:42

JAVA进程占用高内存原因分析与优化方法的相关文章

文章可读性不高的原因分析及改进方法

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 自从高中毕业之后就很少有写文章了,后来也没有接触过语文方面的学习,在工作中发现写作总结概括能力是多么的重要,提高办法之一就是多实践.10月13日,笔者花了一天的时间在A5教程频道投了篇稿子,这算是第一次在网上投稿吧,结果是被无情的退回来了,原因是:文章可读性不高.尽管开始可能会有点不如人意,但这打击性的事实能让人更深刻的认识自己水平.根据前辈

遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高, 直到把内存吃完应用崩溃,但是这个wrapper

问题描述 遇到这样一个问题:通过javaservicewrapper部署应用,wrapper进程占用的内存会一直升高,直到把内存吃完应用崩溃,但是这个wrapper进程会一直运行,同样的的wrapper版本,同样的JDK版本,在另外一台硅谷买的服务器上却没有这个问题,并且wrapper进程占用的内存一直维持在1M左右,没有变化,我们买的是亚马逊redhat7.1,有哪位遇到过类似问题吗?

《JVM故障诊断指南》之3 —— Java 线程: JVM持有内存的分析

前面我们已经讨论过JVM里不同的堆空间,这节我们会给你提供教程,是关于如何从你的活动的应用Java线程中确定它持有多少堆空间,以及在哪里占用.这里有个来自Oracle Weblogic 10.0生产环境的真实案例,它能使你更好的理解分析过程. 我们也会演示这种情况,过多的垃圾收集或者堆空间内存占用问题并不总是由于真实的内存泄露引起,也可能是由于线程执行模型问题和太多的短生命对象引起. 后台 Java线程是JVM基础的一部分.你的Java堆空间内存占用不仅仅是由于静态的和长生命的对象导致,还有可能

win8-windows audio device graph isolation 进程占用超大内存

问题描述 windows audio device graph isolation 进程占用超大内存 win8.1每次开机,这个进程的内存占用都无限膨胀,到最后能占到快2GB,通过手动关开Windows audio service可以解决,但是很麻烦,有什么办法可以从根本上解决这个问题呀? 解决方案 声卡驱动和操作系统不匹配.自己去找找有没有最新的驱动可以更新.

Android Force Close 出现的异常原因分析及解决方法_Android

一.原因: forceclose,意为强行关闭,当前应用程序发生了冲突. NullPointExection(空指针),IndexOutOfBoundsException(下标越界),就连Android API使用的顺序错误也可能导致(比如setContentView()之前进行了findViewById()操作)等等一系列未捕获异常 二.如何避免 如何避免弹出Force Close窗口 ,可以实现Thread.UncaughtExceptionHandler接口的uncaughtExcepti

mysql自动停止原因分析与解决方法

mysql教程自动停止原因分析与解决方法 开始菜单-运行-services.msc 找到mysql的服务并双击 点击恢复选项卡 第一次失败:默认是"不操作",改成"重新启动服务". 在下方的"重新启动服务:___分钟后"添上"0"表示如果服务意外终止则立即重启动. 点击确定使设置生效. 这时候你在任务管理器里结束mysql-nt进程,会发现结束不掉 不过要注意,这样mysql.exe是停不了的,如果要停必须把刚才修改的改回来.

win7蓝屏的原因分析及解决方法

蓝屏很多时候都是突然发生的,大多数是发生在你玩游戏的时候.很多时候是由于CPU一下子处理不过来,或者电脑脑脾气了.像中毒.中木马之类的蓝屏现在已经很好很好了,当然除非你的电脑是裸机,这才有可能. 1 如果是在玩游戏或者电脑弄很多东西的时候,蓝屏而且只有一.两次,当然你如果下次还开那么多东西,那么肯定是再次蓝屏了. 一般情况下都是由于CPU超频,或者内存不足,你可以买条大的内存装上去,基本上就没问题了.也有的时候是你电脑太热了导致CPU一直超频,然后蓝屏了. 2 有的时候也有可能是一些软件的不兼容

XP系统弹出Ravmond.exe应用程序错误的原因分析及解决方法

原因分析: 此电脑上安装了多套安全软件,Ravmond.exe为瑞星杀毒软件的监控程序,且瑞星工作不正常,最后将瑞星卸载掉后解决该问题. 解决方法: 安全软件建议只要安装一套即可,并不是越多越好,如果安装多套软件反而会出现错误冲突导致系统缓慢.关于应用程序错误,内存不能为read提示的问题,有些是在安装某些程序之后出现的,可以找到出现问题的程序软件,卸载即可解决,无需重装系统. 以上就是XP系统弹出Ravmond.exe应用程序错误的原因分析及解决方法,有同样问题的朋友可以按照上述的方法进行设置

PHP程序漏洞产生的原因分析与防范方法说明

 本篇文章主要是对PHP程序漏洞产生的原因分析与防范方法进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 滥用include    1.漏洞原因:    Include是编写PHP网站中最常用的函数,并且支持相对路径.有很多PHP脚本直接把某输入变量作为Include的参数,造成任意引用脚本.绝对路径泄露等漏洞.看以下代码:    ...  $includepage=$_GET["includepage"];  include($includepage);  ...