[JVM]JVM运行时区域划分

根据Java虚拟机规范(Java SE 7版) jvm管理的内存包括以下几个运行时区域:

 
    1. 程序计数器(Program Counter Register) 
  • 程序计数器   是一块比较小的内存空间,可以看作是程序 所执行的字节码的行号指示器。
  • 因为cpu是切换多个线程进行执行,所以为了线程切换后能恢复到正确的位置,每个线程都独有自己的程序计数器,称为线程私有。
  •  此区域是jvm中唯一没有设定任何OutOfMemoryException 的地方
    2. 虚拟机栈(VM Stack)
  •  虚拟机栈同样线程私有。
  •  虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的同时创建栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。方法从调用到结束对应着在栈帧中入栈出栈的过程
  •  局部变量表中存放了编译期间可知的各种基本数据类型(boolean,byte,short,double,long,int,char,float),对象引用(reference类型,指向对象的内存地址),其中64bit的long和int占据2个局部变量空间,其余占1
  •  当进入一个方法的时候,此方法需要在栈帧中分配多大的局部变量空间是完全确定的。
  •  jvm规范中对此区域规定了2个异常,方法请求深度大于jvm允许的深度,抛出stackoverflowEorror,jvm无法申请更多的内存将抛出OutOfMemoryEorror
    3.  本地方法栈(Native Method Stack)
  • 本地方法栈和虚拟机栈发挥的作用基本相同,不同的是本地方法栈执行的native方法,jvm栈执行的是java方法
  • 跟jvm栈一样会抛出StackOverflowError 和 OutOfMemoryError
    4. Java堆 (Heap)
  • 堆是虚拟机管理内存中最大的一块,是被线程所共享的。几乎所有的对象实例都在堆上分配(栈上也可以分配,JIT编译器)
  •  线程共享的堆可能划分出多个线程私有的分配缓冲(Thread Local Allocation Buffer)。
  • 堆可以物理上不连续仅逻辑上连续即可,大多数堆都支持动态扩展,hotspot可以通过 -Xmx和-Xms来控制
  • 堆无法再扩展的时候抛出OutOfMemoryError
    5. 方法区(Method Area)
  • 方法区是各个线程共享的区域,用于存储已经被jvm加载的类信息,常量,静态变量,即时编译器编译好的代码等数据
  • 方法区不属于堆
  • 方法区被习惯称为永久代(Permanent Generation),这里存在GC回收,不过要求比较严格
  • JDK1.7中已经将字符串常量池移除出 永久带进入堆中
  • 会抛出OutOfMemoryError
    6.运行时常量池(Runtime Constant Pool)
  • 运行时常量池是方法区的一部分,Class文件中除了有类的方法,版本,字段,接口等描述信息 意外,还有一项信息是常量池(Constant Pool Table)用于存放编译时期生成的各种字面量和符号引用。
  • 内存大小受制于常量池,会抛出OutOfMemoryError
    7. 直接内存
  • 直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,但是这部分内存也被频繁的使用。
  • JDK1.4中新假如NIO,引入了一种基于通道(channel)与缓冲区(Buffer)的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对这块内存进行操作,能避免在java堆和native堆中来回复制数据         
 
原文地址:https://www.cnblogs.com/coldridgeValley/p/5295877.html