Java虚拟机的运行时数据区域,除了程序计数器之外,都可能会出现outOfMemoryError异常。
一、Java堆溢出
-Xmx:堆最大值 -Xms:堆最小值
Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达的路径来避免垃圾回收机制清除这些对象,那么在对象数量达到最大堆的容量限制后就会产生内存溢出异常。
例:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
解决方法:
1.基于内存调整来改变堆区内存大小以便能够存储更多的对象,但堆内存受到物理内存的限制.
2.从代码上检查是否存在某些对象的生命周期过长、持有状态时间过长的情况,尝试减少程序在运行期的内存消耗。
二、虚拟机栈和本地方法栈溢出
栈容量只有-Xss参数设定。
如果线程请求的栈深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常。
如果虚拟机在扩展栈时无法申请到足够的内存空间,抛出OutOfMemoryError异常。
单线程环境下,无论是栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是StackOverflowError异常。
例:-Xss128k
解决方案:
1.从内存大小上,增加每个线程的虚拟机栈大小
2.从Java程序上无疑就是检查是否出现方法的不合理递归调用,从而减少栈帧的创建和及时的回收。
多线程环境下,每个线程分配到的栈容量越大,可以建立的线程数量越少,建立线程时越容易把剩下的内存耗尽。
例:-Xss2M
解决方案:
1.减少线程数
2.减少最大堆和减少栈容量来换取更多线程。
三、方法区和运行时常量池溢出
-XX:PermSize
方法区容量大小-XX:MaxPermSize
方法区最大容量
JDK1.6运行时常量池在方法区,-XX:PermSize=10M -XX:MaxPermSize=10M
OutOfMemoryError:PermGen Space
JDK1.7运行时常量池在堆内,-Xmx20M -Xms20MOutOfMemoryError:Java Heap Space
自JDK1.7起,字符串常量池从永久代移至Java堆。
JDK8之后的元空间设置参数:
-XX:MaxMetaspaceSize
:设置元空间最大值,默认是-1,不限制,或者说只受本地内存大小限制。
-XX:MetaspaceSize
:元空间初始空间大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载,同时收集器会对该值进行调整:如果释放了大量的空间,就适当减低该值,如果释放空间很少,那么在不超过XX:MaxMetaspaceSize的情况下可以适当提高。
-XX:MinMetaspaceFreeRatio
:在垃圾收集之后控制最小的元空间剩余容量的百分比,可减少因为元空间不足导致的垃圾收集的频率。
四、本机直接内存溢出
-XX:MaxDirectMemorySize最大直接内存容量。不指定,默认与Java堆最大值一样。
由DirectMemory导致的内存溢出,明显的特征是Heap Dump文件中不会看到明显的异常,如果发现OOM之后的Dump文件很小,而程序中有直接或间接使用了NIO。
网友评论