Java虚拟机学习(二)

运行时数据区域:

Java虚拟机在执行Java程序的过程当中会把它所管理的内存划分为若干个不一样的数据区域。这些区域都有各自的用途,以及建立和销毁的时间,有的区域随着虚拟机进程启动而存在,有些区域则依赖用户线程的启动和结束位创建和销毁,根据《Java虚拟机规范》,Java虚拟机将会包含如下几个运行时数据区域:java

(图片来源于网络)网络

程序计数器:

        程序计数器(Progeam Counter Register)是一块较小的内存空间,能够当作当前程序所执行的字节码的行号指示器;数据结构

  • 因为Java虚拟机多线程是经过线程轮流切换并分配处理执行时间的方式来实现的,须要在切换后线程间的程序计数器互不影响,因此线程计数器是线程私有的;多线程

  • 若是线程正在执行的是一个Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址,若是正在执行的是Native方法,计数器为空;spa

  • 此内存区域是惟一一个在Java虚拟机规范中没有规定任何OutOfMemoryError状况的区域线程

Java虚拟机栈:

       Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每一个方法在执行的同时会建立一个栈帧(Srack Frame)用于存储局部变量表、操做数栈、动态连接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。指针

  • 常常咱们把Java内存分为堆内存(Heap)和栈内存(Stack),这种分发比较粗糙的,一般是栈内存只是Java虚拟机栈的局部变量部分。对象

  • 局部变量表存放了编译期可知的各类基本数据类型(boolean、byte、char、short、int、float、long、double)以及对象的引用(reference类型,多是一个指向对象其实地址的引用指针,也多是指向一个表明对象的句柄或其余与此对象有关的位置)和returnAddress类型(指向了一个一条字节码指令的地址);其中64位长度的long和double类型的数据占用2个局部变量空间(Slot),其他数据类型只占1个空间。局部变量表所需内存给空间在编译期分配,在方法运行期间不会改变大小。接口

  • 异常:StackOverflowError当栈深度大于容许的深度时抛出;OutOfMemoryError当扩展时没法申请到足够的内存时抛出生命周期

本地方法栈:

        本地方法栈(Native Method Stack),与虚拟机栈功能相似,只是,本地方法栈只用于Native方法服务,而虚拟机栈用于Java方法服务。虚拟机规范中没有对本地方法栈中使用语言和数据结构作强制规定。因此存在如Sun HotSpot虚拟机这样直接把本地方法栈和虚拟机栈合二为一的。

Java堆:

        Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块,被全部线程共享,在虚拟机启动时建立

  • Java堆是垃圾收集器管理的主要区域,所以不少时候也被叫作“GC堆"

  • 根据Java虚拟机规范的规定,Java堆能够处于物理上不连续的内存空间中,只要逻辑上连续便可

  • 当堆中内存不足,且没法再扩展时,将会抛出OutOfMemoryError异常

    

方法区:

        方法区(Method Area)与Java堆同样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

  • 在Java虚拟机规范中对方法区的限制很是宽松,除了和Java堆同样不须要连续的内存和能够选择固定大小或者可扩展外,还能够选择不实现垃圾回收。这个区域的内存回收主要目标是针对常量池的回收和对类型的卸载,这个区域的垃圾回收如今还比较难使人满意,主要是类型的卸载,条件至关的苛刻。

  • JDK1.7之前Sun HotSpot将GC分代收集扩展到了方法区,省去了专门为方法区编写内存管理代码的工做,但这样更容易形成内存溢出,因此在JDK1.7中,HotSpot已经把本来放在永久代中的字符串常量池移出。

  • Java虚拟机规范规定,当没法知足内存分配需求是,将抛出OutOfMemoryError异常。

运行时常量池:

        运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各类字面量和符号引用,这部份内容将在类加载后进入方法区的运行时存放。

  • Java虚拟机对Class文件每一部分的格式都有严格规定,每个字节用于存储哪一种数据都必须符合规范上的要求才会被虚拟机承认、装载和执行,但对运行时常量池,没有作怎么细节的要求。

  • 运行时常量池具备动态性,即运行期也能够将新的常量放入池中。

  • 一样有OutOfMemoryError异常

直接内存:

     直接内存并不属于java虚拟机规范中指定的内存区域,可是这部份内存也被频繁的使用,并且也可能会致使OutOfMemoryError异常出现。

     最多见使用直接内存的地方时JDK1.4之后加入的NIO的DirectByteBuffer,直接使用系统内存,这样能够避免数据在本地方法栈和java虚拟机栈来回拷贝,即从java虚拟机栈内存拷贝到系统内存。

相关文章
相关标签/搜索