脑图地址: https://naotu.baidu.com/file/0cfdc49ec32194ff306e656a2ef1d002
参考文章:
1.什么是OOM
OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError。意思就是说,当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error(注:非exception,因为这个问题已经严重到不足以被应用处理)
2.为什么会OOM
2.1) 分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少
2.2) 应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出
2.3) OOM的类型
2.3.1) JVM内存模型
==程序计数器:当前线程执行的字节码的行号指示器,线程私有
==JAVA虚拟机栈:Java方法执行的内存模型,每个Java方法的执行对应着一个栈帧的进栈和出栈的操作
==本地方法栈:类似“ JAVA虚拟机栈 ”,但是为native方法的运行提供内存环境。
==JAVA堆:对象内存分配的地方,内存垃圾回收的主要区域,所有线程共享。可分为新生代,老生代
==方法区:用于存储已经被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Hotspot中的“永久代”。
==运行时常量池:方法区的一部分,存储常量信息,如各种字面量、符号引用等
==直接内存:并不是JVM运行时数据区的一部分, 可直接访问的内存, 比如NIO会用到这部分
2.4)OOM分析--heapdump
2.4.1) dump堆的内存镜像
设置JVM参数-XX:
+HeapDumpOnOutOfMemoryError,设定当发生OOM时自动dump出堆信息。不过该方法需要JDK5以上版本
2.4.2) 使用JDK自带的jmap命令
"jmap -dump:format=b,file=heap.bin <pid>" 其中pid可以通过jps获取
2.4.3) 对dump出的文件进行分析
==mat: eclipse memory analyzer, 基于eclipse RCP的内存分析工具。
==jhat:JDK自带的java heap analyze tool,可以将堆中的对象以html的形式显示出来
==IBM HeapAnalyzer
3. OOM异常解决
3.1)java.lang.OutOfMemoryError:Java heap space
3.1.1) 内存模型
==Heap space(堆空间)
== Permgen(永久代)
3.1.2) 代码示例
java -Xmx12m OOM
内存泄漏(没有重写equals)
3.1.3) 解决
增加堆空间 & 减少上述编程错误
3.2)java.lang.OutOfMemoryError:GC overhead limit exceeded
原因
示意你的应用程序在垃圾收集上花费了太多时间但却没有什么卵用。默认超过98%的时间用来做GC却回收了不到2%的内存时将会抛出此错误
代码示例
无限循环加键值对
解决
可以在应用程序启动时添加如下JVM参数-XX:-UseGCOverheadLimit,这样并没有解决任何问题,只是推迟了错误出现的时间, 如果你的应用程序确实内存不足,增加堆内存会解决GC overhead limit问题
修改程序
3.3)java.lang.OutOfMemoryError:Permgen space
原因
太多的类或者太大的类被加载到permanent generation(持久代)
代码示例
生成的类太多
需要注意的是JDK8已经完全移除持久代空间,取而代之的是元空间(Metaspace),所以示例最好的JDK1.7或者1.6下运行
解决
【增加大小】解决初始化时的OutOfMemoryError
解决Redeploy时的OutOfMemoryError
分析dump文件:首先,找出引用在哪里被持有,如下命令导出dump文件:jmap -dump:format=b,file=dump.hprof <process-id>
给你的web应用程序添加一个关闭的hook,或者在应用程序卸载后移除引用
解决运行时OutOfMemoryError
允许JVM卸载类:-XX:+CMSClassUnloadingEnabled配合GC算法 -XX:+UseConcMarkSweepGC
3.4)java.lang.OutOfMemoryError:Metaspace
原因
太多的类或太大的类加载到元空间
解决方案
增加其大小,更改启动配置增加如下参数:-XX:MaxMetaspaceSize = 512m
删除此参数来完全解除对Metaspace大小的限制(默认是没有限制的)
3.5)java.lang.OutOfMemoryError:Unable to create new native thread
原因
当JVM向OS请求创建一个新线程时,而OS却无法创建新的native线程时就会抛出Unable to create new native thread错误
代码示例
代码运行时,很快达到OS的线程数限制
解决
在OS级别增加线程数限制
减少创建的线程数量
3.6)java.lang.OutOfMemoryError:Out of swap space
原因
当应用程序向JVM native heap请求分配内存失败并且native heap也即将耗尽时,JVM会抛出Out of swap space错误
往往是由操作系统级别的问题引起的:
1)操作系统配置的交换空间不足
2)系统上的另一个进程消耗所有内存资源
解决
升级机器以包含更多内存优化应用程序以减少其内存占用
3.7)java.lang.OutOfMemoryError:Requested array size exceeds VM limit
原因
该错误由JVM中的native code抛出。 JVM在为数组分配内存之前,会执行特定于平台的检查:分配的数据结构是否在此平台中是可寻址的。
代码示例
数组里元素太多
3.8)Out of memory:Kill process or sacrifice child
原因
内存杀手(Out of memory killer)”。当内核检测到系统内存不足时,OOM killer被激活,然后选择一个进程杀掉
代码示例
内存杀手(Out of memory killer)
网友评论