运行时数据区域

java运行时数据区域主要分为下面几个:

方法区

虚拟机栈

本地方法栈

程序计数器

java运行时数据区域.jpg

程序计数器

它是一块较小的内存空间,可以看做是当前线程所指定的字节码的行号指示器。字节码解释器工作时就是通过它选取下一条指令的。对于每条线程都有自己独立的程序计数器,所以该区域是线程私有的内存。

如果线程执行的是一个java方法,那么它存储的是正在执行的虚拟机字节码指令的地址;如果执行的是一个Native方法,则存储的值为空。这个区域是Java虚拟机规范中唯一没有规定任何OutOfMemory区域。

java虚拟机栈

它同程序计数器一样时线程私有的。虚拟机栈描述的是Java方法执行的内存模型:每一个方法执行时都会创建一个栈帧用于存放局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法调用都对应着一个栈帧在虚拟机中入栈到处找的过程。

在此区域中Java虚拟机规范中定义了两种异常:如果请求栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果栈是可以动态扩展的,在申请不到足够的内存时也会抛出OutOfMemoryError异常。

本地方法栈

它的作用同java虚拟机栈类似,只不过本地方法栈是为Native方法服务的。Java虚拟机规范没有限制本地方法栈的语言实现,它同样也会抛出StackOverflowError和OutOfMemoryError。

Java堆

Java堆是被所有线程共享的一块内存区域。此区域的唯一作用就是用来存放对象实例,几乎所有的对象实例都是在该区域分配的。

Java堆是垃圾收集器的主要区域。它可以是物理上不连续的内存空间,只要在逻辑上是连续的就行。它的大小可以是固定的,也可以动态扩展的。目前主流实现都是可扩展的,通过(-Xmx和-Xms控制)。如果在堆中没有内存可以完成实例分配,切堆也无法再扩展时将抛出OutOfMemoryError。

方法区

方法区与Java堆一样也是线程共享的内存区域,它用户存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

该区域在HotSpot虚拟机中使用的永久代来实现方法区,所以有时也被称作“永久代”。但是实际上该区域在Java虚拟机中并未详细指出如何实现,它也并不是永久的。

它和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。因为该区域主要针对的是常量池的回收和类型卸载,一般来说这个区域垃圾回收的效果不会很好。

总结

区域

方法区

java堆

本地方法栈

虚拟机栈

程序计数器

是否线程共享

作用

存放被虚拟机加载的类、常量、静态变量和即时编译后的代码等。

存放对象实例。

用来描述Native方法执行的内存模型。

用来描述java方法执行的内存模型。

当前线程所执行字节码的行号指示器。

异常类型

OutOfMemory

OutOfMemory

StackOverflow和OutOfMemory

StackOverflow和OutOfMemory