Java虚拟机在执行Java程序的过程当中会把它所管理的内存划分为若干个不一样数据区域。html
1.有一些是随虚拟机的启动而建立,随虚拟机的退出而销毁,全部的线程共享这些数据区。java
2.第二种则是与线程一一对应,随线程的开始和结束而建立和销毁,线程之间相互隔离。程序员
Java虚拟机所管理的内存将会包括如下几个运行时数据区域
app
1.程序计数器(Program Counter Register)jvm
也叫PC寄存器是一块较小的内存空间,它的做用是存储当前线程所执行的字节码的信号指示器。ide
每一条JVM线程都有本身的PC寄存器。函数
在任意时刻,一条JVM线程只会执行一个方法的代码。该方法称为该线程的当前方法(Current Method)。spa
若是该方法是java方法,那PC寄存器保存JVM正在执行的字节码指令的地址。线程
若是该方法是native,那PC寄存器的值是undefined。设计
此内存区域是惟一一个在Java虚拟机规范中没有规定任何OutOfMemoryError状况的区域。
2.Java虚拟机栈(Java Virtual Machine Stack)
每个JVM线程都有本身的java虚拟机栈,这个栈与线程同时建立,它的生命周期与线程相同。
用于存储局部变量、操做栈、动态连接、方法出口
虚拟机栈描述的是Java方法执行的内存模型:
每一个方法被执行的时候都会同时建立一个栈帧(Stack Frame)用于存储局部变量表、操做数栈、动态连接、方法出口等信息。
每个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表存放了编译器克制的各类基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(Object reference)和字节码指令地址(returnAddress类型)。
JVM stack 能够被实现成固定大小,也能够根据计算动态扩展。
若是采用固定大小的JVM stack设计,那么每条线程的JVM Stack容量应该在线程建立时独立地选定。
JVM实现应该提供调节JVM Stack初始容量的手段。
若是采用动态扩展和收缩的JVM Stack方式,应该提供调节最大、最小容量的手段。
对于32位的jvm,默认大小为256kb, 而64位的jvm, 默认大小为512kb,能够经过-Xss设置虚拟机栈的最大值。不过若是设置过大,会影响到可建立的线程数量。
JVM Stack 异常状况:
StackOverflowError:当线程请求分配的栈容量超过JVM容许的最大容量时抛出.
OutOfMemoryError:若是JVM Stack能够动态扩展,可是在尝试扩展时没法申请到足够的内存去完成扩展,或者在创建新的线程时没有足够的内存去建立对应的虚拟机栈时抛出。
3.本地方法栈(Native Method Stack)
Java虚拟机可能会使用到传统的栈来支持native方法(使用Java语言之外的其它语言编写的方法)的执行,这个栈就是本地方法栈.
若是JVM不支持native方法,也不依赖与传统方法栈的话,能够无需支持本地方法栈。
若是支持本地方法栈,则这个栈通常会在线程建立的时候按线程分配。
异常状况:
StackOverflowError:若是线程请求分配的栈容量超过本地方法栈容许的最大容量时抛出.
OutOfMemoryError:若是本地方法栈能够动态扩展,而且扩展的动做已经尝试过,可是目前没法申请到足够的内存去完成扩展,或者在创建新的线程时没有足够的内存去建立对应的本地方法栈,那Java虚拟机将会抛出一个OutOfMemoryError异常。
注:以上三个数据区属于各个线程单享的,每一个线程建立时都会建立此三个数据区。各个线程之间相互隔离,互不影响。
4.方法区(Method Area)
方法区是可供各条线程共享的运行时内存区域。存储了每个类的结构信息,例如:运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法。
方法区在虚拟机启动的时候建立。
方法区的容量能够是固定大小的,也能够随着程序执行的需求动态扩展,并在不须要过多空间时自动收缩。
方法区在实际内存空间中能够是不连续的。
Java虚拟机实现应当提供给程序员或者最终用户调节方法区初始容量的手段,对于能够动态扩展和收缩方法区来讲,则应当提供调节其最大、最小容量的手段。
Java 方法区异常:
OutOfMemoryError: 若是方法区的内存空间不能知足内存分配请求,那Java虚拟机将抛出一个OutOfMemoryError异常。
运行时常量池(Runtime Constant Pool)
运行时常量池是每个类或接口的常量池(Constant_Pool)的运行时表现形式,它包括了若干种常量:编译器可知的数值字面量到必须运行期解析后才能得到的方法或字段的引用。
运行时常量池是方法区的一部分。每个运行时常量池都分配在JVM的方法区中,在类和接口被加载到JVM后,对应的运行时常量池就被建立。
在建立类和接口的运行时常量池时,可能会遇到的异常:
OutOfMemoryError:建立类和接口时,若构造运行时常量池所需的内存空间超过了方法区所能提供的最大内存空间后时抛出.
5.Java堆(Heap)
在JVM中,堆是可供各条线程共享的运行时内存区域,也是供全部类实例和数据对象分配内存的区域。
Java堆是Java虚拟机所管理的内存中最大的一块。
经过-Xms和-Xmx来控制初始堆大小和最大堆大小
Java堆载虚拟机启动的时候就被建立,堆中储存了各类对象,这些对象被自动管理内存系统(Automatic Storage Management System,也便是常说的“Garbage Collector(垃圾回收器)”)所管理。这些对象无需、也没法显示地被销毁。
Java堆的容量能够是固定大小,也能够随着需求动态扩展,并在不须要过多空间时自动收缩。
Java堆所使用的内存不须要保证是物理连续的,只要逻辑上是连续的便可。
JVM实现应当提供给程序员调节Java 堆初始容量的手段,对于可动态扩展和收缩的堆来讲,则应当提供调节其最大和最小容量的手段。
Java 堆异常:
OutOfMemoryError:若是实际所需的堆超过了自动内存管理系统能提供的最大容量时抛出。
参考原文:http://chenzhou123520.iteye.com/blog/1585224
http://www.open-open.com/lib/view/open1383745340321.html