JVM内存区域(Run-Time Data Areas)

Java内存区域(Run-Time Data Areas)

JVM定义了多种类型的运行时数据区,用于程序执行期间。其中一些数据区在JVM启动时被创建并且在JVM退出时被销毁。另一些数据区是属于单个线程的,这种数据区在线程创建时被创建并且在线程退出时被销毁。
在这里插入图片描述
Java虚拟机在运行程序时会把其自动管理的内存划分为以上几个区域,每个区域都有的用途以及创建销毁的时机,其中蓝色部分代表的是所有线程共享的数据区域,而绿色部分代表的是每个线程的私有数据区域。

  • 堆(Heap)
    JVM的堆是供所有的JVM线程共享的。所有的对象实例和数组都在这里分配内存。
    它在虚拟机启动时被创建,堆内存中的对象不会被显示回收,而是通过一个自动存储管理系统(即 garbage collector,垃圾回收器)。

  • 方法区(Method Area)
    JVM的方法区是供所有的JVM线程共享的。主要用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
    值得注意的是在方法区中存在一个叫运行时常量池(Runtime Constant Pool)的区域,它主要用于存放编译器生成的各种字面量和符号引用,这些内容将在类加载后存放到运行时常量池中,以便后续使用。

  • 程序计数器(The pc Register, The Program Counter Register):
    属于线程私有的数据区域,每个JVM线程都有一个Java虚拟机栈,是一小块内存空间,主要代表当前线程所执行的字节码行号指示器。字节码解释器工作时,通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

  • Java虚拟机栈(Java Virtual Machine Stacks):
    属于线程私有的数据区域,每个JVM线程都有一个Java虚拟机栈,Java虚拟机栈与线程同时创建,代表Java方法执行的内存模型。每个方法执行时都会创建一个栈桢来存储方法的的变量表、操作数栈、动态链接方法、返回值、返回地址等信息。每个方法从调用直结束就对于一个栈桢在虚拟机栈中的入栈和出栈过程,如下:
    在这里插入图片描述

  • 本地方法栈(Native Method Stacks):
    属于线程私有的数据区域,这部分主要与虚拟机用到的 Native 方法相关,一般情况下,我们无需关心此区域。

方法区(Method Area)存储了什么内容

方法区是各个线程共享的内存区域。存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等等。下图显示了JVM加载类的时候,方法区存储的信息:
方法区是各个线程共享的内存区域。存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等等。下图显示了JVM加载类的时候,方法区存储的信息:
在这里插入图片描述
1、类信息

  • 类型的全限定名
  • 超类的全限定名
  • 直接超接口的全限定名
  • 类型标志(该类是类类型还是接口类型)
  • 类的访问描述符(public、private、default、abstract、final、static)

2、类的常量池

存放该类型所用到的常量的有序集合,包括直接常量(如字符串、整数、浮点数的常量)和对其他类型、字段、方法的符号引用。常量池中每一个保存的常量都有一个索引,就像数组中的字段一样。因为常量池中保存中所有类型使用到的类型、字段、方法的字符引用,所以它也是动态连接的主要对象(在动态链接中起到核心作用)。

3、字段信息(该类声明的所有字段)

  • 字段修饰符(public、protect、private、default)
  • 字段的类型
  • 字段名称

4、方法信息

方法信息中包含类的所有方法,每个方法包含以下信息:

  • 方法修饰符
  • 方法返回类型
  • 方法名
  • 方法参数个数、类型、顺序等
  • 方法字节码
  • 操作数栈和该方法在栈帧中的局部变量区大小
  • 异常表

5、类变量(静态变量)

指该类所有对象共享的变量,即使没有任何实例对象时,也可以访问的类变量。它们与类进行绑定。

6、 指向类加载器的引用

每一个被JVM加载的类型,都保存这个类加载器的引用,类加载器动态链接时会用到。

7、指向Class实例的引用

类加载的过程中,虚拟机会创建该类的Class实例,方法区中必须保存对该对象的引用。通过Class.forName(String className)来查找获得该实例的引用,然后创建该类的对象。

8、方法表

为了提高访问效率,JVM可能会对每个装载的非抽象类,都创建一个数组,数组的每个元素是实例可能调用的方法的直接引用,包括父类中继承过来的方法。这个表在抽象类或者接口中是没有的,类似C++虚函数表vtbl。

9.运行时常量池(Run-Time Constant Pool)
相对于静态常量池,运行时常量池具有动态性,在程序运行的时候可能将新的常量放入运行时常量池中,比如使用String类的intern方法。

官方文档:
https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-2.html#jvms-2.5
其他参考文档:
《深入理解JVM虚拟机》

全面理解Java内存模型(JMM)及volatile关键字
Java虚拟机–方法区(运行时常量池)
Java虚拟机(JVM)的方法区(Method Area)存储了什么内容?
Java虚拟机的静态常量池和运行时常量池

发布了516 篇原创文章 · 获赞 89 · 访问量 73万+

猜你喜欢

转载自blog.csdn.net/yzpbright/article/details/104645831