java OOM异常

1. 堆溢出

  1. 集合

    死循环向集合加元素(强引用)

  2. 老年代没有足够连续空间装新的对象或大对象

    大对象:很长的字符串和数组,需要连续空间

 

  解决:    

    要解决这个区域的异常,一般的手段是首先通过内存映像分析工具(如Eclipse Memory Analyzer)对dump 出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。使用Eclipse Memory Analyzer 打开的堆转储快照文件。

    如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots 相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息,以及GC Roots 引用链的信息,就可以比较准确地定位出泄漏代码的位置。

    如果不存在泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数(-Xmx 与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。

 

2. 栈溢出

  1. StackOverflowError

    根本原因是: 某个线程所需的栈内存超过了JVM的限制,而此时物理内存仍有足够的可用空间。

    (单线程下只会出现这种情况)

  2. OutOfMemoryError

    根本原因是:(操作系统管理的)物理内存已没有足够的可用内存分配给JVM的栈使用。

 

3. 方法区溢出

  大量的类占满内存

  CGLib操作字节码生成大量动态类

  框架对类增强时会用到CGLib这类字节码技术,增强的类越多,方法区需要的内存越多

4. 直接内存溢出

  Heap Dump文件很小,没有明显异常,程序又使用了NIO,则可能出现这种原因

  ps:元数据区分配在直接内存,不断创建static对象,有可能使可使用直接内存越来越小

原文地址:https://www.cnblogs.com/GY8023/p/13717836.html