yihau

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。其中有些区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。下图左边是所有线程共享区域,右边是线程私有区域。

1、程序计数器     
  程序计数器内存空间较小,主要记录下一条需要执行的字节码的位置。Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的(时分复用),因此在任何一个确定的时刻,一个cpu只会处理一个线程中的指令。因此,为了保证线程切换过程中恢复正确的位置,每个线程都持有一个独立的程序计数器,所以,程序计数器是线程私有的内存。而且程序计数器区域不会发生OutOfMemeoryError。
2、Java虚拟机栈
  栈也是线程私有的,其生命周期伴随线程。栈里面是一个个的栈帧栈帧是方法调用时产生的一种数据结构,栈帧包括局部变量表,操作数栈,动态链接,方法出口等信息。每个方法抵用直至完成的过程就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。其中栈帧的局部变量表中存放了编译期可知的各种基本数据类型、对象引用(reference类型,一般是指针,指向对象的位置)和returnAddress类型。
         栈有两种异常情况:线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常(这种可能是递归太深,栈中无法再容纳下一个栈帧);虚拟机栈可以动态扩展,如果无法申请到足够的内存,就会抛出OutOfMemoryError异常。
3、本地方法栈
   本地方法栈与Java虚拟机栈类似,不同的是Java虚拟机栈为执行Java方法服务,而本地方法栈为虚拟机执行Native方法服务,所以有些虚拟机直接将这两个栈合二为一。本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。
4、Java堆
  Java堆一般来说是Java虚拟机管理的内存中最大的一块。Java堆是所有线程共享的内存区域,其伴随这虚拟机进程而生,用来存放对象实例。The heap is the runtime data area from which memory for all class instances and arrays is allocated。但是随着JIT编译器的发展,栈上分配等技术会使所有对象都分配在堆上变得不那么“绝对”。
         Java堆是垃圾收集器管理的主要区域,Java堆还可以细分为新生代和老年代,再细致一点新生代还可以分为Eden空间,FromSurvivor 空间和ToSurvivor空间。堆的大小可以通过Xms和Xmx参数来控制。如果堆中没有内存来分配实例,并且无法扩展的时候,将会抛出OutOfMemoryError异常。
5、方法区 
  方法区(MethodArea)线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Hotspot虚拟机通过永久代来实现方法区,这样可以像管理Java堆一样来管理方法区的垃圾收集。在JDK1.7的Hotspot中已经把原来放在永久代的字符串常量池移出。方法区会抛出OutOfMemoryError异常。
6、运行时常量池
  运行时常量池(Runtime ConstantPool)是方法区的一部分。用于存放编译器生成的各种字面量(字符串常量)和符号引用(java.lang.StringBuilder类的全名),运行期间也可能将新的常量防区池中。常量池内存溢出为OutOfMemoryError。
posted on 2018-03-09 20:44  yihau  阅读(169)  评论(0编辑  收藏  举报