java内存区域

运行时数据区域  java

  java虚拟机在执行java程序的过程当中会把它管理的内存分为不一样的数据区域,不一样的数据区域功能不一样,以及它的建立和销毁时间不一样,有的区域随着虚拟机的启动而存在,有的区域依赖用户线程的启动和结束而创建和销毁。数组

 

程序计数器:是一块小的内存,能够认为是当前线程所执行的字节码的行号指示器。(执行到底哪里了),多线程之间轮流切换分配处理器的执行时间,在任什么时候刻一个处理执行一个线程中的指令,线程切换后为了能及时恢复到正确的位置,每一个线程内都须要一个程序计数器,各个线程之间的计数器互不干扰,是线程的私有内存。
若是程序执行的是java方法,计数器记录的是正在执行的字节码的指令地址,若是执行的是本地方法native method,技术器则为空(undefined)
技术器是惟一一块在java虚拟机规范中没有任何规定OutOfMemoryError状况的区域
 

 Java虚拟机栈:Java虚拟机栈描述的是java方法执行的模型,这部分区域也是线程私有的,生命周期和线程相同。每一个java方法执行的时候都会建立一个栈帧(stack frame),这个栈帧用于存储局部变量表,操做站、动态连接、方法出口等信息。每一个方法的调用到执行完毕都是对应着一个栈帧在java虚拟栈从入栈到出栈的过程。多线程

 

局部变量表:~存放了在编译期可知的各类基本数据类型,对象引用类型 (不是对象自己)和 returnAddress类型(执行一条字节码指令的地址)。其中64位的长度的long和double类型的数据会占用2个局部变量空间(slot),其他的数据类型都只占用1个,局部变量表所须要的内存空间在编译期间就已经分配完成。当java方法调用执行的时候,这个方法在栈帧中分配多大的内存已经彻底肯定了,运行期间是不会改变局部变量表的大小。
在java虚拟机规范中,对此区域规定了两种异常:(1)当线程请求的栈深度大于虚拟机所容许的深度,则会抛出StackOverflowError (2)若是虚拟机动态扩展,当扩展到没法申请到足够的内存空间的时候(系统内存有限),会抛出OutOfMemeryError
 
本地方法栈:Native Method Stack 和 java虚拟机栈发挥的做用是同样,只不过java虚拟机栈是执行java方法,而本地方法栈是执行native方法。一样的道理,本地方法也会抛出StackOverflowError和OutOfMemeryError
 
 
Java堆:java heap 是虚拟机中管理的内存中最大的一块,是全部线程共享的一块内存区域。java heap的惟一目的就是存放对象实例,几乎全部的对象实例都在这里分配内存。java虚拟机规范描述的是全部的对象实例和数组都要在堆上分配。
java堆是垃圾收集器管理的主要区域,所以也称为"GC堆".
Java堆能够处于物理上不连续的内存空间中,只须要逻辑连续便可。能够实现成固定大小,也能够实现为可扩展(主流虚拟机都设计成可扩展,经过-Xmx 和 -Xms控制),当java heap没有内存完成实例分配,堆也没法再扩展,将会抛出 OutOfMemeryError
 
 
方法区:Method Area 和 java堆同样,是全部线程共享的内存区域。用于存储虚拟机加载的类信息,静态变量,常量,即时编译器编译后的代码数据等。
运行时常量池:运行时常量池是方法区的一部分,class文件除了有类的版本,方法、接口、字段等的描述信息,还有一项信息就是常量池,用于存放编译时生成的各类字面量和符号引用,而这部分信息在类加载后存放在方法区中的运行时常量池中。运行时常量池受到方法区内存的限制,运行时常量池没法申请到内存时也会抛出OutOfMemeryError异常。
运行时常量池相对于class文件常量池的一个特色是具备动态性,也就是说并不是只在编译期间,class文件的常量池的内容才能进入运行时常量池,在运行期间,也有可能将常量放入运行时常量池中,例如:String类的intern()方法
 
 
直接内存:直接内存不是运行时数据区的一部分,不是java虚拟机规范定义的内存区域。在NIO类中,使用native方法直接在堆外分配内存,而后经过在java堆中DirectByteBuffer对象对象做为这块内存的引用进行操做。避免了java堆和native堆之间的数据来回复制,提升了性能。本机的直接内存不会受到java堆大小的限制,可是仍是会受本机内存大小的限制。当配置各个内存区域大小的时候,忽略了直接内存,使得各个区域内存大小之和大于物理内存限制,则会抛出OutOfMemeryError异常。
相关文章
相关标签/搜索