OutOfMemory原因分析
1. Java heap space(JVM无法在堆中分配对象)
a). 内存泄漏
java应用程序一直持有对象的引用,gc无法释放,如对象池,线程池
b). 配置问题
Xmx 配置太小,调大堆空
c). finalize 方法过度使用
对象被回收之前需要做一些额外操作,如释放占有的资源。
gc时不会立即回收该对象,而是将该对象放到RefrenceQueue中,由Finalizer线程消费。
由于Finalizer线程 优先级较低,导致对象积压。
尽量避免使用finalize方法
2. GC overhead limit exceeded
垃圾回收器一直在运行,但是效率很低。
超过5次会抛出OutofMemory的异常。
解决方法:
a) 生成heap dump文件,判断是否有内存泄漏
b)设置-XX:-UseGCOverheadLimit
3. Request array size exceeds VM limit
请求的数组大小超过jvm限制。
解决方案:
a)调大堆内存大小
b)程序的bug,看看是不是由于内存计算失误导致请求分配大数组
4. MetaSpace
元空间用尽,调整MaxMetaSpaceSize
5. 本地对内存分配失败或者本地内存即将用尽
致命错误处理机制
生成致命错误 日志文件
使用Dtrace工具分析日志文件,(操作系统提供该功能)
6. Unable to create native threads
创建线程的过程如下:
6.1. Java应用程序发送JVM请求创建一个新的线程
6.2 JVM本地代码代理调用操作系统API,创建操作系统级别的线程
6.3 操作系统尝试创建Native Thread,并分配线程栈,受Xss的限制,太小会出现StackOverFlow异常,如递归调用。
6.4 创建native Thread失败
6.5 抛出异常。
创建Native Thread失败的可能原因如下:
a) 内存设置太小 Xss
b) ulimit 限制
1)使用ulimit -a 查看操作系统对各种资源的限制
其中 -u: processes 限制了一个进程可以创建的最大线程数
2) 通过 ulimit -u 9999 设置
c) sys.kernal.thread-max :限制操作系统全局线程数。
1)查看: cat /proc/sys/kernel/threads-max
2)修改:修改/etc/sysctl.conf
d) sys.kernal.pid_max 限制
系统全局的PID号数值限制