Java虚拟机:内存模型详解

版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习!算法

      咱们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪一个区域呢?当咱们建立一个对象实例的时候,虚拟机要为对象分配内存,Java虚拟机又是如何配份内存的呢?这些都涉及到Java虚拟机的内存划分机制,今天咱们就来探究一下Java虚拟机的内存模型。数据结构

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

      

 

       以上就是Java虚拟机运行时数据区域的划分,每一块内存区域都有它的职责,存放着不一样的运行时数据。学习

       虚拟机栈
spa

       Java虚拟机栈是线程私有的,每个线程在这个区域都有一块所属的内存区域,它的生命周期与线程相同,随线程启动而生,随线程消亡而灭。虚拟机栈描述的是Java方法执行的内存模型,每个线程都对应着虚拟机栈区域里的一个栈数据结构,因为一个线程的方法调用链可能会很长,每个方法在执行时都会建立一个栈帧,栈帧就是线程对应的栈数据结构的栈元素,栈帧用于存储局部变量表、操做数栈、动态连接等信息。局部变量表存放了方法参数和方法内部定义的局部变量,包括各类基本数据类型和对象引用类型等信息。常常听到有的程序猿粗糙的把虚拟机内存划分为堆内存和栈内存,这种划分只能说明大多数程序猿比较关注的、与对象内存分配关系最密切的是这两块内存区域,其中的“栈内存”就是这里所说的虚拟机栈,而虚拟机栈里咱们程序猿最为关注的就是局部变量表部分。
线程

       本地方法栈对象

       本地方法栈也是线程私有的,它与虚拟机栈发挥的做用类似,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法(本地方法)服务。在Java虚拟机规范中并无对本地方法栈的实现作强制规定,有的虚拟机甚至直接把虚拟机栈和本地方法栈合二为一。blog

       生命周期

       Java堆是全部线程所共享的一块内存区域,也是Java虚拟机所管理的内存中最大的一块。这块内存的惟一目的就是存放对象实例,几乎全部的对象实例都在这里分配内存。Java堆是垃圾收集器管理的主要区域,从内存回收的角度看,因为如今收集器基本都采用分代收集算法,因此Java堆还能够细分为新生代和老年代。新生代还能够再细分为Eden区域、FromSurvivor区域和ToSurvivor区域。不管怎么划分,都与存放的内容无关,存储的任然都是对象实例。进一步划分的目的是为了更好的回收或者更快的分配内存。进程

       方法区

       方法区与Java堆同样,是线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。方法区是一个逻辑区,具体属于哪一块物理内存根据不一样的虚拟机实现而定。在HotSpot的实现中,方法区逻辑上与堆内存隔离,物理存储上倒是是属于Java堆的一部分。不少人把方法区称为“永久代”,实际上是HotSpot使用永久代来实现方法区而已。其余的虚拟机实现并无永久代这一律念。Java虚拟机规范对方法区的限制很是宽松,除了和Java堆同样不须要连续的内存和能够选择固定大小或者可扩展外,还能够选择不实现垃圾回收。通常来讲不会在方法区进行垃圾回收,在这一区域进行回收的效果很难让人满意。当方法区没法知足内存分配需求时会抛出内存溢出异常。

       运行时常量池是方法区的一部分,用于存放编译期间生成的各类字面量和符号引用,这部份内容将在类加载后进入方法区的运行时常量池中存储。

       程序计数器

       程序计数器是一块很小的内存空间,它也是线程私有的。它能够看做是当前线程所执行的字节码的行号指示器,经过改变这个计数器的值来选取下一行须要执行的字节码指令。因为Java虚拟机的多线程是经过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个肯定的时刻,一个处理器内核只会执行一条线程中的指令,所以,为了线程切换后可以恢复到正确的执行位置,每条线程都须要有一个独立的程序计数器,各条线程之间互不影响,独立存储。

       以上就是Java虚拟机的内存模型划分,这是咱们程序猿必须掌握的原理,弄清Java虚拟机的内存模型,是理解虚拟机内存分配和垃圾回收的基础,以此做为总结。

相关文章
相关标签/搜索