Java虚拟机运行时数据区

        最近在看《深入理解Java虚拟机》,想把书中比较重要的知识码下来,留着备用加深理解。

 

        JVM在执行Java程序的过程中会将所管理的内存划分为若干个不同的数据区域,根据《Java虚拟机规范(Java SE 7版)》的规定,包括以下几个运行时数据区域。


 
 

  1. 程序计数器:可以当作是当前线程所执行的字节码的行号指示器,字节码解释器通过改变程序计数器来选取下一条需要执行的字节码指令,如:分支、循环、跳转、异常处理、线程恢复等。Java的多线程是通过时间片轮转来实现的,即处理器在任何一个确定的时刻都只会执行一条线程的指令。因此为了线程切换后能恢复到正确的执行位置,每个线程都有一个独立的程序计数器。如果线程执行的是Java方法,那么程序计数器记录的是当前虚拟机执行字节码指令的地址;如果线程执行的是Native方法,那么程序计数器为空。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
  2. Java虚拟机栈:Java虚拟机栈也是线程私有的,生命周期和线程一致。虚拟机栈是描述Java方法执行的内存模型:每个方法在执行同时都会创建一个栈帧(栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用开始到介绍都对应一个栈帧在虚拟机栈中的入栈到出栈的过程。局部变量表所需的内存空间在编译期间就已经确定了(完成分配了),运行期不能修改大小。当线程请求的栈深度大于虚拟机栈深度,将抛出StackOverflowError,当虚拟机栈扩展时无法申请到足够的内存,将抛出OutOfMemoryError。
  3. 本地方法栈:与Java虚拟机栈类似,Java虚拟机栈服务于Java方法,本地方法栈是服务于Native栈(有的虚拟机将二者合二为一:Sun HotSpot虚拟机)。
  4. Java堆:被所有线程共享的一块内存区域。它在虚拟机启动时创建,用于存放对象实例,是垃圾收集管理的主要区域(“GC堆”)。可以使用JVM参数控制大小(-Xmx -Xms),如果堆中没有内存可以完成实例的分配(new对象的时候内存不足),并且堆无法拓展时,将抛出OutOfMemoryError。
  5. 方法区:被所有线程共享的一块内存区域。它用于存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。当方法区无法满足内存分配的需求时,将抛出OutOfMemoryError。
  6. 运行时常量池:String常量池这个概念经常会在面试中提到。常量池用于存放编译期生成的各种字面量和符号引用,这些内容在类加载后存放于方法区的运行时常量池。程序运行期间也能将数据放入常量池中(如:String的intern方法)。当常量池无法申请到内存时,将抛出OutOfMemoryError。
  7. 直接内存:服务器物理内存(通过Native方法分配的堆外内存,不受JVM控制的内存),扩展时内存不足将抛出OutOfMemoryError。

猜你喜欢

转载自ashnl007.iteye.com/blog/2259997
今日推荐