java虚拟机管理内存划分

2018-11-07  本文已影响36人  https迷路了

java虚拟机会在执行程序的过程中把管理的内存划分成几个数据区:程序计数器、java 虚拟机栈、本地方法栈、java堆、方法区。 

1、程序计算器:

这个比较好理解,就是线程执行字节码的行标,就是用来记录程序执行到哪里了,这样程序才知道接下来应该运行哪里。因为是为每个线程记录了,所以比较理所当然的就是线程私有啦。

这个计算器的值也很好理解,如果是执行的是Java代码,记录的就是字节码指令地址;如果执行是native方法(大概就是一个java调用的非java的接口),那计数器就是空值。

这个计算器还有一个特点就是唯一一个java虚拟机规范没有规定任何OutOfMemoryError情况的区域。

2、java 虚拟机栈:

虚拟机栈其实就是java方法执行的内存模块,方法的运行的这个过程就是对应一个栈帧(方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息)从虚拟机栈进栈出栈的过程。这部分也是线程私有的。

java虚拟机规范对虚拟机栈规定了两种的异常情况:

1)线程请求栈的深度大于java虚拟机规范规定的深度,这时会抛出StackOverFlowError异常。

2)当虚拟机栈动态拓展时(大部分虚拟机是允许的),拓展时无法申请到足够的内存,这时会抛出OutOfMemoryError异常。

3、本地方法栈 :

与虚拟机栈很类似,主要的区别在于本地方法栈是为虚拟机使用到Native方法服务的。但是java虚拟机规范并没有强制对本地方法栈进行规定,所以有一些虚拟机甚至会把虚拟机栈和本地方法栈合二为一。

4、java堆:

一般情况下,java堆是java虚拟机管理中的最大一块。java堆在java虚拟机启时创建,是被所有线程共享的,是大多数的实例都要在这里分配内存的(栈上分配和标量替换导致一些实例不在堆上分配)。是垃圾收集器管理的主要区域。

java虚拟机规范规定,java堆只需要内存是逻辑连续的就可以,不一定是要物理连续(主流虚拟机通过-Xmx和-Xms来控制java堆的拓展)。拓展时无法申请到足够的内存,这时会抛出OutOfMemoryError异常。

5、方法区:

这部分的作用主要用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码。这部分是被所有线程共享的。

java虚拟机规范规定,方法区也是只需要内存是逻辑连续的就可以,不一定是要物理连续,可以动态拓展,并且可以选择不实现垃圾收集。虽然这部分实现垃圾收集效果并不好,但是也是有必要的。如果没有垃圾收集,可能会出现内存泄漏的情况。拓展时无法申请到足够的内存,这时会抛出OutOfMemoryError异常。

方法区有一个部分叫运行时常量池。java虚拟机规范规定并没有对运行时常量池作任何细节的要求。运行时常量池具有动态性,预置在Class文件中常量池的内容能进入运行时常量池,运行期间的新的常量也是可能将加入。

上一篇下一篇

猜你喜欢

热点阅读