欢迎来到天天文库
浏览记录
ID:14398368
大小:54.79 KB
页数:17页
时间:2018-07-28
《深入理解java虚拟机--自动内存管理机制》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、写在前面本文介绍的Java虚拟机(JVM)的自动内存管理机制主要是参照《深入理解Java虚拟机》(第2版)一书中的内容,主要分为两个部分:Java内存区域和内存溢出异常、垃圾回收和内存分配策略。因此我也会分为两个部分来讲解,但这并不代表这两个部分在JVM中是分割的。反之,其实这两个部分关联性很强。只不过为了便于介绍,所以我才分开来讲。在介绍它们详细内容之前,我首先会给出两幅思维导图以便读者可以了解一下里面所包含的内容,然后我会根据思维导图中的知识点一一为大家进行介绍。01第一部分Java内存区域
2、和内存溢出异常下面我将对图中所涉及到的部分进行介绍运行时数据区域由于直接内存(DirectMemory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是这部分内存也被频繁地使用,而且也可能导致内存溢出异常(OutOfMemoryError)出现,所以也放到这部分进行介绍。Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途以及创建和销毁的时间。有的区域(线程共享的数据区域)随着虚拟机的启动而存在,有的区域(线
3、程隔离的数据区域)则要依赖用户线程的启动和结束来创建或者是销毁。程序计数器程序计数器(ProgramCounterRegister)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。学过《计算机组成原理》这门课之后我们知道----在计算机中,其实程序计数器就是一个寄存器,依据不同计算机细节的差异,它可以存放当前正在被执行的指令,也可以存放下一个要被执行的指令。由此,我们可以对“当前线程所执行的字节码的行号指示器”有更好的理解。在虚拟机的概念模型中,字节码解释器工作时就是通过改
4、变这个计数器的值来选取下一条需要执行的字节码指令。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。因此为了线程切换之后能够恢复到正确的执行位置,每条线程都需要拥有一个独立的程序计数器,各条线程之间计数器互补影响,独立存储。所以程序计数器是线程私有的内存(线程隔离)。如果线程正在执行的是一个Java方法,这个计数器记录的就是正在执行的虚拟机字节码指令的地址;如果正在执行的是N
5、ative方法,那么这个计数器的值就为空(Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。Java虚拟机栈和程序计数器一样,Java虚拟机栈(JavaVirtualMachineStack)也是线程私有的,即它的生命周期和线程的相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧(StackFrame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就
6、对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。我们常常说的栈内存其实就是现在讲的虚拟机栈,或者说是虚拟机栈中局部变量表部分。局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,可能是指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。其中64位长度的long和d
7、ouble类型的数据会占用2个局部变量空间(Slot),其余数据类型只占用1个。局部变量表所需要的内存空间在编译时期完成分配。当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。本地方法栈本地方法栈(NativeMethodStack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别就是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。其实虚拟机规范中对本地方发栈中方法所使用的语
8、言、使用方式以及数据结构都没有强制规定,因此具体的虚拟机可以自由地实现它。甚至在有的虚拟机(如SunHotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemory异常。Java堆对于大多数应用来说,Java堆(JavaHeap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块数据区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存
此文档下载收益归作者所有