java内存区域与内存异常

Posted by on May 21, 2017

1.JAVA虚拟机运行的时候会分配不同的数据区域,分为以下区域。 image

简述
程序计数器(program counter register)只占用了一块比较小的内存空间,至于小到什么程度呢,这样说吧,有时可以忽略不计的。

作用
可以看作是当前线程所执行的字节码文件(class)的行号指示器。在虚拟机的世界中,字节码解释器就是通过改变计数器的值来选取下一条执行的字节码指令,分支、循环、跳转、异常处理、线程恢复都需要这玩意来实现的,NB吗?

特性
因为处理器在一个确定是时刻只会执行一个线程中的指令,线程切换后,是通过计数器来记录执行痕迹的,因而可以看出,程序计数器是每个线程私有的。
如果执行的是java方法,那么记录的是正在执行的虚拟机字节码指令的地址的地址,如果是native方法,计数器的值为空(undefined)。

这个内存区域是唯一一个在java虚拟界规范中没有规定任何OutOfMemoryError的情况的区域。至于为什么没有这个异常呢,要是一个计数的功能在出这个异常,那么我也是醉了。

2.JAVA虚拟机栈

私有的生命手气和线程的生命周期一样,每个方法在执行的时候都会创建一个栈帧(存储局部变量,操作数 栈,动态链接,等)每个方法懂执行到调用完毕都是入栈和出栈的过程,如果线程请求的深度大于大于虚拟机所允许的最大深度,就会抛出
stackoverflowerror栈溢出的异常,虚拟机栈也可以扩张,但是超过了扩张的深度就会oom异常。

3.本地方法栈

本地方法栈和JAVA虚拟机栈没什么区别就是,一个是执行java方法的栈一个是执行native方法的栈,也会报stackoverflowerror栈溢出的异常,和oom

4.JAVA堆

是被所有线程所共享的区域,在虚拟机启动的时候创建,此区域唯一的目的就是存放对象的实例,JAVA堆中还可以细分为新生代和老年代,该区域是可以动态配置的(通过-Xmx和-Xms控制),如果在堆中没有完成内存实例分配,并且当前堆也无法在扩展就会报OOM

5,方法区

是各个线程共享的区域,他用于存储已经被虚拟机加载的类的信息,即编译后的代码,这就是与JAVA堆的区别。