[关闭]
@chenxuxiong 2016-05-28T06:16:21.000000Z 字数 2260 阅读 1694

栈溢出,堆溢出,永久代溢出,内存泄漏排查

JAVA虚拟机


1.虚拟机栈和本地方法栈溢出:

2.堆溢出

    方案:不断创建对象实例,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,当对象数量到达最大对的容量限制的时候,就会抛出内存溢出异常。
    设置堆最小值:-Xms 最大值: -Xmx
    结果:OutofMemoryError: Java Heap space

排查是内存溢出还是内存泄漏

内存泄漏:使用eclipse插件 (eclipse memory analyzer)对Dump出来的堆转储快照进行分析,查看对象到GCRoots的引用链。如果是对象和引用链之间存在相关联导致垃圾收集器无法回收他们,查看泄漏对象的类型信息和GC Roots引用链的信息,就能确定内存泄漏的位置。

堆溢出:如果不存在泄漏,那么就检查堆参数(-Xms和-Xmx)是否能调大一些,从代码上检查是否存在某些对象生命周期过长、持有状态过长的情况,尝试减少程序运行期的内存消耗。

JVM由XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
JVM由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

该错误常见场合:

a) 应用中有很多Class,web服务器对JSP进行precompile时。
b) Webapp下用了大量的第三方jar,其大小超过了JVM默认的大小(4M)时。

3.方法区和运行时常量池溢出

1.常量池溢出

不断调用String.intern()方法,添加不同的字符串到字符串常量池中,导致抛出OOM (PerGen Space) 异常
String.intern()是一个Native方法,作用是:如果字符串常量池中已包含一个等于此String对象的字符串,则返回代表池中这个字符串的对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象引用

2.方法区溢出

方案一:运行时产生大量的类去填满方法区。
方案二:借助CGLib直接操作字节码运行时,生成大量的动态类。
最终结果:OutofMemoryError:PermGen space

4.直接内存溢出

方案:直接通过反射获取Unsafe实例进行内存分配,unsafe.allocateMemory
为什么需要用反射:Unsafe类的getSafe()方法限制了只有引导类加载器才会返回实例,设计者希望只有rt.jar中的类才能使用Unsafe的功能。
为什么不用DirectByteBuffer分配内存:它抛出异常时并没有真正想操作系统申请分配内存,而是通过计算得知内存无法分配,遇上手动抛出异常。

5.内存泄漏

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注