谈论JVM内存溢出问题

1、问题描述

      这两天公司项目的项目进行测试,服务器会偶尔出现访问不通,EJB远程调用全部失效的情况,经过对JVM监控,发现是JVM内存FullGC造成系统停顿造成的。目前基础系统jboss启动jvm内存设置为3G,之前出现过out of memory heap 的错误。现在正常开发情况下,基础系统平均一两天就会因为内存爆满,出现系统停顿,不得不重启jboss来解决。

      一开始一直认为EJB不稳定,一般个别接口远程调用不通,经过查看系统日志发现有OOM的异常。

相关工具:

         Jconsole:jdk自带的jvm简单监控工具,直接cmd—jconsole即可使用

         Jvisualvm:jconsole高级版本,比jconsole信息详细些,cmd-jvisualvm即可使用

         Jprofiler:性能监控工具,可以同步检测程序运行过程中jvm的各个参数,类,线程的实时情况。同时也可以分析dump。

         EclipeseMemory Analyzer:多用于离线分析dump日志,可以给出内存溢出的建议,工具具体使用较为专业,需要对jvm内部结构了解。


监测情况如图:



主要是老年代内存不足,及FullGC造成的。


名词介绍:

          新生代:主要用来存放新生的对象,对象更新速度快,短时间内产生大量的“死亡对象”

          老年代:主要存放应用中生命周期长得内存对象(具体介绍看百度)

引起内存溢出的原因可能是:


1、JVM参数使用默认的不能够满足我们的需要,需要根据我们系统的需要对新生代和老年代进行内存分配。

2、大量使用本地缓存(如大量使用hashmap作为K/V缓存)的应用,在逻辑集群造成即到达的内存浪费,因为每个逻辑节点上都有一份缓存。

这时候可以考虑把本地缓存改为集中式缓存。·

3、不恰当的数据结构导致内存占用过大(例如:HashMap<String,String>结构中来存储数据文件空间效率太低)

总结:

       通过修改JVM的参数,系统改善不是很明显,只能延缓,不能从根本上解决问题。最根本的着手点还是我们的代码,可以考虑和代码走查的相关负责人配合。优化我们的代码,比如:优化map是很有必要的,代码中是否存在不合理的for循环或者是递归调用,由于循产生过多重复的对象实体,或者是list、map等集合对象是否有使用完后,未清除的问题,导致不能被GC回收。


最终的原因还是由于自己代码中使用多租户+级联导致不能回收,问题的原因知道,但是不清楚为什么他俩放一起使用就不行了,该问题还在研究中。


你可能感兴趣的:(jvm,内存溢出)