Java虚拟机在执行Java程序中会把它所管理的内存划分为若干个数据区域,这些区域有各自的用途,以及生命周期,有些依赖虚拟机进程启动而存在,有些依赖用户线程的启动和结束而创建和销毁算法
程序计数器是一块较小的内存空间,能够看做是当前线程所执行的字节码的指示器,字节码解释器经过改变这个计数器的值来选取下一条须要执行的字节码指令。
因为Java虚拟机的多线程是经过线程调度(轮询)切换分配处理器执行时间的方式来实现的,在任何一个肯定的时刻都只会执行一条线程中的指令。因此为了当线程切换后能找到以前执行指令的位置,每一个线程都须要有一个独立的程序计数器,各个线程之间的程序计数器互相不影响,这类内存区域为“线程私有”的内存区域。多线程
Java虚拟机栈和程序计数器同样,Java虚拟机栈(如下简称栈)也是“线程私有”的,它的生命周期和线程相同,每一个方法在执行时都会建立一个栈帧(Stack Frame)用于存储局部变量表(方法中定义的变量),操做数栈,动态连接,方法出口等信息。每一个方法从调用直至执行完成的过程,就是对应着一个栈帧在栈中入栈和出栈的过程。函数
本地方法栈和Java虚拟机栈同样,本地方法栈用于执行Native方法spa
Java堆是被全部线程共享的一块内存区域,在虚拟机启动时被建立。此内存区域的惟一目的就是存放对象的实例,几乎全部的对象实例都在这里分配内存,Java堆是垃圾收集器管理的主要区域,因为如今不少收集器都采用分代收集算法,全部Java堆还能够细分为:新生代和老年代。能够经过-Xmx和-Xms来控制堆内存的大小线程
方法区和Java堆同样,也是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。通常也称做为“永代区”(Permanent Generation),这里要特别说明一下,由于咱们使用的主流虚拟机HotSpot的设计团队用“永代区”来实现方法区,这样HotSpot的垃圾收集器就能够像管理堆那样管理这部份内存,在JDK1.7的HotSpot中,已经把字符串常量池移出“永代区”了。设计
直接内存并非虚拟机运行时数据区的一部分,可是若是你使用了NIO的类,就会致使OutOfMemoryError异常出现
NIO引入了一种基于通道(Channle)与缓冲区(Buffer)的I/O方法,它可使用Native函数库直接分配堆外的内存,而后经过一个存储在Java堆中的DirectByteBuffer对象做为这块内存的引用进行操做。这样能避免在Java堆和Native堆中来回复制数据的开销,本机直接内存的分配不会受到Java堆大小的限制,可是会受到物理内存的限制,全部也会抛出OutOfMemoryError异常。对象
“程序计数器”和“Java虚拟机栈”是线程私有的,而“Java堆”和“方法区”是线程共享的生命周期
除了虚拟机运行时内存,在Java中使用NIO类能够直接操做本机内存。进程
方法区在HotSpot中用于存放各类“常量信息”内存
Java堆中存放了程序中全部的对象实例