websphere 内存溢出处理

  1. 启用进程跟踪,可以产生
  2. Java虚拟机发生一次堆内存申请失败(Allocation Failure),由于Java虚拟机规范规定,在发生Allocation Failure之后必须进行GC操作,Java虚拟机会进行一次GC操作。所以系统缓慢的原因在于

    <1> 对象的内存申请失败
    <2>频繁的GC本身会占用大量CPU时间。

    同时,如果内存申请操作连续失败,即使GC之后也不能申请内存,就会发生core dump,并且同时存在heapdump文件,这说明WebSphere系统发生了内存溢出(OOM)。

    频繁发生GC和系统core dump的原因是一致的,即内存总是申请失败(Allocation Failure)。
  3. 通常情况下,频繁发生core dump是由于以下两类原因导致
    1 内存泄漏

    堆内存申请失败通常是由于系统中存在大量不能被GC操作所删除的对象,由于GC只删除没有引用指向的对象,所以,如果在编程的时候没有消除对过期对象的引用(将引用置为null),那么此过期对象就无法被删除。大量的过期对象会导致大量的堆内存被占用。

    2 内存碎片问题

    通常情况下,对于Java虚拟机出现,只需要配置heap最大最小值,以及maxPermSize,但是这种情况仅限于SUN的Java虚拟机。对于IBM的JVM,情况就完全不一样

    对于Sun的JVM来说,它的GC策略默认是复制、分代算法。也就是说,它会将heap分成不同的几个区,譬如Solaris JVM中最上面有两个大小相等的区。GC时刻,将一个区的存活对象复制到另外一个对等区,垃圾对象就算遗弃了。这样在heap里面,就不存在碎片问题。

    另外Sun的JVM有单独的方法区,也就是Permanent Generation,方法区中保存的一般是Class对象,而不是普通的实例对象,也就是JVM的元数据。

    IBM的JVM默认GC策略并没有采取复制、分代。这个可以从GC日志分析出来。它不像Sun的JVM那样,有个单独的方法区,它的方法区就放在Java Heap里面。在IBM的JVM里面,这些对象一般分配在称为k-cluster和p-cluster里(cluster又是属于Heap),而后者一般是临时在heap里面申请。并且,这些cluster是不能GC,或是被移动重排的(Compact过程)。这就导致Java Heap里面就如同蜂窝,但不同的蜂孔又不能合并,于是,当我们程序里面产生一个大对象,譬如2M的数组(数组必须分配在连续的内存区)时,就没有可分配空间了,于是就报告OOM。这些不能被移动的cluster之间的空隙就称为所谓的碎片。此时,JVM的Heap利用率可能不到50%。

    再说一个细节,k-cluster能够存放1280个类对象,第一个p-cluster大小为16K,默认存放类似于JNI对象和线程对象等不能移动的对象(pinned),然后k-cluster中存放不下的类对象也会放在p-cluster中,第一个p-cluster满了之后,后续的p-cluster大小只有2K,一个类对象大小是256字节。

    此类碎片问题无法通过重整解决。碎片只是一个通俗的说法,正确的含义是每两个p簇之前的空隙过小,可以视为碎片。由于p簇是不能移动不能删除的,所以碎片的大小完全是由类的加载情况决定的。也就是说可能某次was启动之后恰巧不会oom,也可能启动不久就会oom。

    要想完全解决,只能通过实验测试出恰当的-Xp和-Xk的值
    所以,升级到1.3.1 SR7以后的版本就可以用-xK和-xP了。
    说到底,这是IBM JVM 1.4设计上的缺陷,IBM JVM 1.5已经不存在P、K族的问题了,并且1.5的GC机制已经在向SUN的实现靠拢,在JVM的实现中,SUN/HP是一个流派,JRocket/IBM是一个流派,当中数IBM最异类,JRocket虽然不使用分代GC机制,但却很少出现OOM的问题
    IBM JDK 1.5已经重新写了JVM。据说GC算法改了,碎片问题应该会好很多。

参考地址:http://www.verydemo.com/demo_c89_i231239.html

猜你喜欢

转载自xinghen1314579.iteye.com/blog/2072655