虚拟机结构-运行时数据区
程序计数器(Program Counter Register)
程序计数器是一个记录着当前线程所执行的字节码的行号指示器。这个内存区域有以下特点:
Java虚拟机栈(Program Counter Register)和本地方法栈
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧用于存储局部变量、操作数栈、动态连接、方法出口等信息。本地方法栈和虚拟机栈比较相似,区别是虚拟机栈执行Java方法,本地方法栈为虚拟机使用到的Native方法服务。这个内存区域有以下特点:
这个区域会出现两种异常情况:
StackOverflowError:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError;
如果虚拟机栈可以动态扩展,扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常;
方法区(Method Area)
方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区也叫Non-Heap(非堆),在HotSpot虚拟机上,很多人也将方法区成为“永久代(Permanent Generation)”,原因是这个区域大部分情况下不会进行GC,即使对这个区域做了GC,回收的空间也很少。方法区中还有一个运行时常量池,用于存放编译期生成的各种字面量和符号引用。方法区域的特点如下:
Java堆内存(Java Heap)
Java堆是虚拟机中最大的一块内存,虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例。堆内存区域可以是固定大小的(通过-Xmx和-Xms指定),也可以是动态扩展的。堆内存的特点有:
直接内存
直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是会被频繁使用。NIO(New input/output)是JDK1.4中新加入的类,引入了一种基于通道(channel)和缓冲区(buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过堆上的DirectByteBuffer对象对这块内存进行引用和操作。一般不会设置直接内存的大小,当各个区域内存总和大于物理内存时会出现OutOfMemoryError异常。