今天一个同事让我帮忙分析一下他们的系统,系统经常出现很多heapdump文件,于是我拿到他们的文件进行了分析
发现设置的内存最大最小内存是相同的,但是JVM是IBM的,可能就会出现问题
Sun的虚拟机,一般可以设置heap最大最小值一致,也是推荐的做法。因为Sun GC策略默认采用的是复制、分代算法。也就是说它会将heap分成不同的几个区,例如Solaris JVM中最上面有两个大小相等的区。GC时刻,将一个区的存活对象复制到另外一个对等区,垃圾对象就算遗弃了。这样在heap里面,就不存在碎片问题。另外,根据Java对象的存活期不同,将之转移到不同的区(Tenured区),存活最长的在最底部(火车算法),这也就是分代模型
IBM的JVM,情况就完全不一样。默认GC策略并没有采取复制、分代。它不像Sun的JVM那样,有个单独的方法 区,它的方法区就放在Java Heap里面。JVM规范里面并没有要求方法区的必须存放的位置,因为它只是一个JVM实现问题,在IBM的JVM里面,这些对象一般分配在称为k簇和p簇里(簇又是属于Heap),而后者一般是临时在 heap里面申请。并且,这些cluster是不能GC,或是被移动重排的(Compact过程)。这就导致Java Heap里面就如同马蜂窝,但不同的蜂孔又不能合并,于是,当我们程序里面产生一个大对象,譬如2M的数组(数组必须分配在连续的内存区)时,就没有可分 配空间了,于是就报告OOM。这些不能被移动的簇就称为所谓的碎片。此时,JVM的Heap利用率可能不到50%。
所以需要根据不同的jvm进行不同的参数设置,如果是sun的,建议使用最大最小内存一样的方式,如果是 IBM的,就建议不要将最大最下内存设置成一样的,这样可以减少出现OOM的机率。
下一步把通过jca,ja,ha的方式分析的过程,由于今天拿到的heapdump文件的内容缺少gc的日志,所以等他们发过来新的heapdump文件后在整理分析过程。