java内存溢出异常
java内存溢出异常
简述
- 对于java而言,java在
虚拟机(java virtual machine)
的自动内存管理机制下,不需要为每一个new的对象进行free/delete方法,而且不容易出现内存泄漏和内存溢出的问题,看起来很美好。 - 不过,正是因为java把内存交给了虚拟机,一旦出现了内存泄漏和内存溢出的问题,如果不了解虚拟机是怎么使用内存的,那么管理将是一个艰巨的工作。
运行时的数据区域
虚拟机在执行java过程的过程中,会将他所管理的内存划分为若干个不同的数据区域。这些区域各自有用途,以及创建和销毁时间,有的区域随着虚拟机进程启动而存在。
程序计数器
- 程序计数器是指在一快较小的内存空间中,它的作用可以看作是当前线程所执行的字节码的行号指示器。字节码的解释器工作室通过改变这个解释器的指来选取下一跳需要执行的字节码命令,分支、循环、跳转、异常处理、线程恢复等功能都要依赖这个计数器完成。
java多线程的实现
- java多线程是通过线程间轮流切换并且分配处理器的执行时间的方式来实现的,所以在任意一个确定的时刻,一个处理器只会执行一条线程中的命令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这条内存区域为线程私有区域。
- 如果线程正在执行一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果正在执行的是Native方法,这个计数器的只为空。次内存区域是唯一一个在java虚拟机中没有规定outOFMemoryError情况的区域。
java虚拟栈
- 和程序计数器一样,Java虚拟机栈 也是线程私有的,
它的生命周期与线程相同
。虚拟机描述的是java执行的内存模型。
程序理解
OutOfMemoryError
程序
Object object = new Object();
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<BB> bbs = new ArrayList<>();
while (true) bbs.add(new BB());
}
}
class BB{
}
Object object 对应的Java栈的本地变量表中,作为一种reference类型数据出现
new Object() 对应的java栈的堆,形成了一块存储了Object类型所有实例数据值(Instance Data,对象中各个字段)的结构话内存。堆中还能查到此对象的类型数据(如对象类型,父类,实现接口,方法等)的地址信息,这些类型数据存储在方法区中。
[GC (Allocation Failure) [PSYoungGen: 8192K->1008K(9216K)] 8192K->5065K(19456K), 0.0077794 secs] [Times: user=0.04 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) --[PSYoungGen: 9200K->9200K(9216K)] 13257K->19432K(19456K), 0.0117182 secs] [Times: user=0.05 sys=0.01, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 9200K->0K(9216K)] [ParOldGen: 10232K->9747K(10240K)] 19432K->9747K(19456K), [Metaspace: 3076K->3076K(1056768K)], 0.1220499 secs] [Times: user=0.38 sys=0.00, real=0.12 secs]
[Full GC (Ergonomics) [PSYoungGen: 7859K->8085K(9216K)] [ParOldGen: 9747K->7637K(10240K)] 17607K->15723K(19456K), [Metaspace: 3081K->3081K(1056768K)], 0.1289125 secs] [Times: user=0.48 sys=0.01, real=0.13 secs]
[Full GC (Allocation Failure) [PSYoungGen: 8085K->8067K(9216K)] [ParOldGen: 7637K->7637K(10240K)] 15723K->15705K(19456K), [Metaspace: 3081K->3081K(1056768K)], 0.0958057 secs] [Times: user=0.53 sys=0.00, real=0.10 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at Test.main(Test.java:6)
[Full GC (Ergonomics) [PSYoungGen: 8192K->0K(9216K)] [ParOldGen: 7637K->372K(10240K)] 15829K->372K(19456K), [Metaspace: 3106K->3106K(1056768K)], 0.0036833 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 9216K, used 82K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
eden space 8192K, 1% used [0x00000007bf600000,0x00000007bf614938,0x00000007bfe00000)
from space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
to space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
ParOldGen total 10240K, used 372K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
object space 10240K, 3% used [0x00000007bec00000,0x00000007bec5d120,0x00000007bf600000)
Metaspace used 3113K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 342K, capacity 388K, committed 512K, reserved 1048576K
StackOverflowError
public class JavaVmStackSOF {
private int statckLeng = 1;
public void add(){
statckLeng ++;
add();
}
public static void main(String[] args) {
JavaVmStackSOF javaVmStackSOF = new JavaVmStackSOF();
try {
javaVmStackSOF.add();
}
catch (Exception e){
System.out.println("stackLeng: "+ javaVmStackSOF.statckLeng);
throw e;
}
}
}
Exception in thread "main" java.lang.StackOverflowError
at JavaVmStackSOF.add(JavaVmStackSOF.java:6)
at JavaVmStackSOF.add(JavaVmStackSOF.java:6)
at JavaVmStackSOF.add(JavaVmStackSOF.java:6)
JVM参数
-Xoss参数
- 设置本地方法栈大小虽然存在,但实际上是无效的
-Xss 参数
- 栈容量只能由这个参数设定