专栏首页波波烤鸭java虚拟机运行时数据区介绍

java虚拟机运行时数据区介绍

  最近打算将java虚拟机的相关知识点整理出来。本文先介绍下java虚拟机运行时分配的各个区域的作用

运行时数据区域

java虚拟机在程序执行的过程中会把它所管理的内存划分为若干个不同的数据区域,每个区域都有各自的用途。结构图如下:

程序计数器

  程序计数器(Program Counter Register)是一块较小的内存空间,这块区域是线程私有的。作用是当前线程所执行的字节码的行号指示器(记录器)。   java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现。在任何一个确定的时间点,一个处理器(对于多核处理器就是一个内核)都只会执行一条线程中的指令,因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。各个线程之间计数器是相互不影响的。独立存储。所以程序计数器的作用也比较突出。保存当前线程执行的位置。

java虚拟机栈

  和程序计数器一样java虚拟机栈也是线程私有的。它的生命周期和线程相同。   虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,用来存储局部变量表操作栈动态链接方法出口等信息。每个方法从调用直到执行完成的过程,都对应一个栈幁在虚 拟机栈中从入栈到出栈的过程。

  在编译程序代码的时候,栈帧需要多大的局部变量表,多深的操作数栈都已经完全确定了,并且写入到方法表的code属性中,因此一个栈帧需要分配多少内存,不会受到运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

  一个线程中的方法调用链路可能会很长,很多方法都处于同时执行的状态。对于执行引擎来说,在活动线程中,只有处于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法。 执行引擎运行的所有字节码指令只针对当前栈帧进行操作,在概念模型上,典型的栈帧结构如图所示:

本地方法栈

  本地方法栈和虚拟机栈所发挥的作用是非常相似的。他们的区别仅仅是java虚拟机栈是为java方法调用服务的,而本地方法栈主要是为虚拟机调用到native方法服务的。   如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。本地方法接口需要回调Java虚拟机中的Java方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个Java栈。如下是虚拟机栈和本地方法栈的图示

java堆

  Java堆(Java Head)是java虚拟机中所管理的内存中最大的一块。 java堆是被所有线程共享的一块内存区域。java堆的唯一目的就是存放对象实例。几乎所有的对象实例都在这里分配内存。   Java堆是垃圾收集器管理的主要区域。因此垃圾收集器也被称作"GC堆",在垃圾收集器的角度Java堆还可以细分为:新生代老年代在细致的区分有:Eden空间,From Survivor空间,To survivor空间等从内存分配的角度来看,线程共享的Java堆中还可以划分出每个线程私有的分配缓冲区(Thread Local Allocation Buffer TLAB)。   不管如何划分,都与存放内容无关,无论哪个区域,存放的都是对象实例,划分的目的是为了更好的回收内存或者更快的分配内存。后面文章中具体介绍各个区域如何分配的等。   java堆中的内存地址物理上可以不是连续的。只要逻辑上连续即可。

-Xxm和-Xms 控制堆的大小。

方法区

  方法区(Method Area)与java堆一样,是各个线程共享的内存区域。用来存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。   方法区的大小不必是固定的,jvm可以根据应用的需要动态调整。同样方法区也不必是连续的。方法区可以在堆(甚至是虚拟机自己的堆)中分配。jvm可以允许用户和程序指定方法区的初始大小,最小和最大尺寸。   方法区同样存在垃圾收集,因为通过用户定义的类加载器可以动态扩展Java程序,一些类也会成为垃圾。jvm可以回收一个未被引用类所占的空间,以使方法区的空间最小。   对每个加载的类型,jvm必须在方法区中存储以下类型信息:

  1. 这个类型的完整有效名
  2. 这个类型直接父类的完整有效名(除非这个类型是interface或是 java.lang.Object,两种情况下都没有父类)
  3. 这个类型的修饰符(public,abstract, final的某个子集)
  4. 这个类型直接接口的一个有序列表

除了以上的基本信息外,jvm还要为每个类型保存以下信息:

  1. 类型的常量池( constant pool)
  2. 域(Field)信息
  3. 方法(Method)信息
  4. 除了常量外的所有静态(static)变量

运行时常量池

  运行时常量池(Runtime Constant Pool) 是方法区的一部分。jvm为每个已加载的类型都维护一个常量池。常量池就是这个类型用到的常量的一个有序集合,包括实际的常量(string, integer, 和floating point常量)和对类型,域和方法的符号引用。池中的数据项象数组项一样,是通过索引访问的。 因为常量池存储了一个类型所使用到的所有类型,域和方法的符号引用,所以它在java程序的动态链接中起了核心的作用。

直接内存

  直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分。但是这部分内存也会被频繁的使用到。   在java中使用NIO的时候,Channel和缓冲区(Buffer),它可以使用Native函数库直接分配堆外内存。然后通过存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样可以在某些场景中显著提高性能。避免了在java堆和Native堆中来回复制数据。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JVM的内存对象介绍[创建和访问]

      作为java程序员对应Object应该是非常熟悉的,但是对于对象在JVM中的一些情况并不是很清楚,所以本文就来记录下对象在JVM中的一些内容

    用户4919348
  • JVM垃圾回收算法实现的方式

      通过前面的介绍我们清楚了JVM中对象是如何判断存活及垃圾回收算法。那么垃圾回收的算法到底是怎么实现的呢?因为HotSpot虚拟机在对对象回收的时候对执行的效...

    用户4919348
  • NIO之缓冲区【直接和非直接缓冲区】

      字节缓冲区跟其他缓冲区类型最明显的不同在于,它们可以成为通道所执行的 I/O 的源头和/或目标。其实发现通道只接收ByteBuffer作为参数这个将Chan...

    用户4919348
  • 深入理解java虚拟机学习笔记(一) java内存区域与相关异常

    jvm运行时所管理的内存将会分为如下几个区域:程序计数器、虚拟机栈、本地方法栈、方法区、堆区。其中,方法区和堆区由所有线程共享,程序计数器、虚拟机栈、本地方法栈...

    冬天里的懒猫
  • java虚拟机 (JVM)主要组成部分(学习笔记)

    一,类加载器 (1) 加载 引导类加载器 扩展类加载器 应用程序加载器 (2)连接 验证(字节码是否存在) 准备(为静态变量分配内存) 解析(同方法的原始,代替...

    用户7886150
  • JVM内存模型

    java404
  • JVM GC 那些事(一)- JVM 运行时内存划分

    对于经常使用 Spark 的人来说,如何设置 driver 或 executor 的内存大小,如何尽量减少 GC 相信不会陌生。要做好这两点,除了 Spark ...

    codingforfun
  • JVM内存结构

    按照Java虚拟机规范的规定, JVM自动管理的内存将包括以下几个运行时的数据区域:

    烟草的香味
  • JVM程序计数器,虚拟机栈,本地方法栈

    入门小站
  • 动态数据竞争检测方法实验分析(二)

    上一篇文章主要分析了各个检测方法在检测能力上的优劣。这篇文章主要分析一下各个检测方法对程序造成的影响以及可扩展性。

    chain

扫码关注云+社区

领取腾讯云代金券