OutOfMemoryError知多少

Java堆溢出
Java堆内存OOM是最常见的内存溢出 。异常堆栈信息“java.lang.OutOfMemoryError” 会跟着进一步提示“Java heap space” 。
一般通过内存映像分析工具对dump出来的堆转储快照进行分析,重点确认内存中的对象是否是必要的 , 也就是分析清楚到底是出现了内存泄漏还是内存溢出 。
内存泄漏解决
通过工具查看泄漏对象到GC Roots的引用链,泄漏的对象是通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收它们的 。
掌握了泄漏对象的类型信息,以及GC Roots引用链的信息,就可以定位泄漏代码的位置了 。
内存溢出解决
如果不是泄漏 , 就说明这个对象确实需要活着 。那就应当检查虚拟机的堆参数了(-Xmx 与-Xms),与及其物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存损耗 。
虚拟机栈和本地方法栈溢出
在Java虚拟机规范中描述了两种异常:
线程请求的栈深度大于虚拟机所允许的最大深度 , 将抛出StackOverflowError异常虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
其实本质上区分点在于程序是单线程和多线程 。
单线程下很难模拟出OOM的情况,抛出的基本上都是StackOverflowError 。
多线程下,基本上每个线程的栈分配的内存越大,反而越容易产生OOM(Java.lang.OutoOfMemoryError :unable to create new native Thread)的异常 。
多线程应用下,出现StackOverflowError异常一般都有错误堆栈的信息 , 相对较为容易的找到问题原因 。
虚拟机的默认参数 , 栈深度多数情况在2000以内完全没有问题,对于正常的方法调用,基本上都可以满足 。
如果建立过多线程导致的内存溢出,只有两种办法来解决此类问题 。
减少线程数减少堆栈容量来换取更多的线程(-Xss j降低的每个线程栈大小的容量) 。
永久代/元空间溢出
永久代是Hotspot虚拟机方法区的具体实现,存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等 。JDK8后 , 元空间替代了永久代,元空间使用的是本地内存 。
出现内存溢出的异常信息为:java.lang.OutOfMemoryError: PermGem space
或者java.lang.OutOfMemroyError: Metaspace
一般解决思路如下:
1、通过参数设置永久代(-XX:MaxPermSize)或者元空间(-XX:MaxMetaspaceSize )的大小
2、检查代码中是否存在大量的反射操作
3、dump之后通过工具检查是否存在大量由于反射生成的代理类 。
swap溢出
swap溢出(java.lang.OutOfMemoryError:Out of swap space)一般是操作系统导致的 , swap分区大小分配不足或者其他进程消耗了所有的内存 。
拆出去其他的进程,或者增加swap分区大小以及增加机器内存大小 。
【OutOfMemoryError知多少】以上就是朝夕生活(www.30zx.com)关于“OutOfMemoryError知多少”的详细内容,希望对大家有所帮助!

猜你喜欢