运行时数据区组成_深入JVM(一)

运行时数据区

        JVM在执行java程序时,会把其所管理的内存划分成多个区域,每个区域都有不同用途,每个区域的创建和销毁时间也不同.这每块内存都属于运行时数据区域.

        这些区域有程序计数器,方法区,堆,虚拟机栈,本地方法栈

程序计数器

        程序计数器是当前线程所执行的字节码行号指示器 . 它所用内存空间很小,是线程私有的 .

        它的作用是记录当前线程执行到字节码指令的地址(class文件的哪个地方),若该线程等待 ,处理器时间片重新调度到该线程,程序计数器可以让处理器知道接下来要执行哪行字节码指令.

        分支,循环,跳转,异常处理,线程回复等都需要以来程序计数器来完成

Java虚拟机栈

        虚拟机栈是线程私有的,其生命周期与线程相同

        在栈中,每执行一个方法前都会创建一个栈帧,来储存局部变量表,操作数栈,动态链接.方法出口等信息 .每个方法从调用到完成,就对应着栈中一个栈帧的压栈到弹出的过程.

        栈帧的局部变量表用来储存8种基本数据类型,reference类型(对象的引用),returnAddress类型(方法结束后执行的字节码指令的地址) . 储存在局部变量表的数据是以32位的Slot变量空间进行存储 , double和float类型则需要两个slot空间存储.

        一个方法对应的栈帧中局部变量表所需内存空间早已在编译期间就分配完成 , 当进入一个方法,虚拟机栈对应压入一个栈帧,次栈帧局部变量表空间大小完全确定

本地方法栈

        和虚拟机栈相似,本地方法栈用来服务Native方法

        在我们最常用的HotSpot虚拟机中,本地方法栈与java虚拟机栈合二为一

扫描二维码关注公众号,回复: 4136375 查看本文章

        Java堆是一块线程共享的内存区域 , 它在虚拟机启动时分配创建 , 它是JVM内存里最大的一块内存了,但是它的目的只有一个 ---- 存放对象实例 .

        堆大概可以分为新生代和老年代 .再分的细一些为 Eden区 ,From Survivor区 ,To Survivor区和老年代 . java堆也是垃圾收集(GC)的主要区域 ,GC方式在每个带都有不同的规则(分代收集算法).

        Java堆为了更快的分配,更好的回收内存,可能会划分出多个线程私有的分配缓冲区,来提升管理内存的速度 .

        Java堆可以处于物理上不连续的内存空间中 , 只需要逻辑上连续就好 .

方法区

        虚拟机规则定义方法区应是储存已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据 . 是线程共享的内群区域 .

        这部分区域比较特殊,虚拟机规范这部分区域属于堆 , 但是其作用又与堆有较大差异 .虚拟机如何实现方法区,则不受虚拟机规范约束. HotSpot为例 , jdk1.7之前,方法区为永久代,其垃圾回收受java堆GC分带收集算法管理 . 1.7将String常量池移入堆中 , jdk1.8中永久代被完全移除 ,将类加载信息放入一个线程共享的元空间内.

        JRockit与HotSpot合并,这样表面上是避免永久区的OOM,实际是为了更好的与JRockit合并 , JRockit 和 J9虚拟机就没有永久代的概念.

======================================================================

运行时常量池

        用来存放编译生成的字面量和符号引用 , 是方法区的一部分

直接内存

        直接内存不属于虚拟机规范中定义的内存区域,当然不属于运行时数据区.

        NIO使用Native函数库直接分配堆外内存 , 然后通过一个DirectByteBuffer对象作为这块内存的引用,可以大幅度减轻堆的负担,提高虚拟机性能 .

猜你喜欢

转载自blog.csdn.net/start_lie/article/details/81192962