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对象,有可能使可使用直接内存越来越小