Java堆溢出
JVM运行时分区的堆区是占比最大的,它用来存储对象的,每当我们new一个对象,而且要保证这个对象到GC Roots 那些对象是有路径可达的(不可达就有很大可能性被清除),那么当对象的数量超过最大堆容量后就会产生内存溢出异常(Out Of Memory)。
我们可以自己设置JVM的相关参数:
-Xms:用来设置堆的最小值;
-Xms:用来设置堆的最大值。
Java堆内存出现的OOM异常其实是我们实际开发中最常见的内存溢出的一种情况。Java堆内存溢出时,Java异常堆栈信息“java.lang.Out Of Memory”会进一步提示"java heap space"这就很清楚的告诉我们溢出发生在堆上。
下面补充两个知识点内存泄漏和内存溢出:
内存泄漏:泄露对象不能被GC;
内存溢出:此时内存对象应该存活。就有两种方式可以解决:1.根据JVM堆参数与物理内存相比较检查是否应该把JVM堆内存调大;2.或者检查对象的生命周期是否过长。
虚拟机栈和本地方法栈溢出
现在都在用的HotSpot把虚拟机栈和本地方法栈合在一起实现,所以对于HotSpot这个虚拟机来说,栈容量只需要由Xss一个参数就能设置。我们都知道每当有一个线程出现,JVM就会给他分配固定大小的栈空间供他使用,在这个线程调用方法的同时,栈内部会创建一个个栈帧来描述方法的执行过程,随着一个个栈帧的创建,当这个空间超过刚开始分配给这个线程的空间时,就会抛出StackOverFlow异常;还有一种情况就是当要为一个线程创建栈空间时发现已经没有足够的空间去分配时就会抛出OOM异常。
两种异常对应的解决方法:
- 因为出现StackOverFlowError这个异常时我们有错误堆栈可以去追溯,问题出现在哪里会被找到。虚拟机默认参数其实够我们日常的调用(包括递归)。
- 如果是因为多线程导致的内存不够用而出现的内存溢出问题,在不能再少线程数的情况下,减少最大堆和减少栈的容量来能给更多线程创分配栈空间。