前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >运行时数据区

运行时数据区

作者头像
DioxideCN
发布2023-01-13 13:53:54
1970
发布2023-01-13 13:53:54
举报

运行时数据区

官方解读

Chapter 2. The Structure of the Java Virtual Machine (oracle.com) The Java Virtual Machine defines various run-time data areas that are used during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only when the Java Virtual Machine exits. Other data areas are per thread. Per-thread data areas are created when a thread is created and destroyed when the thread exits.

5007d3825e2c830e40879b9660234bdc
5007d3825e2c830e40879b9660234bdc

方法区

基本概念

JVM 只有一个方法区,且是被所有 JVM 线程共享的,方法区的生命周期是与 JVM 互相绑定的。方法区拥有以下特点:

  1. 方法区是各个线程共享的内存区域,在虚拟机启动时创建
  2. 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器变异后的代码等数据
  3. 对染 Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又有一个别名叫做 Non-Heap(非堆),目的是与 Java 堆区分开来
  4. 当方法区无法满足内存分配需求时,讲会抛出 OOM 异常
  5. 方法区在 JDK8 中就是 Metaspace 元空间,在 JDK6 和 7 中式 Perm Space
  6. 运行时常量池属于方法区的一部分在方法区中进行分配
  7. 方法区是线程安全的。由于所有的线程都共享方法区,所以,方法区里的数据访问必须被设计成线程安全的。例如,同时有两个线程都访问方法区中的同一个类,而这个类还没有被装入 JVM ,那么只允许一个线程去装载它,而其它线程会被阻塞

运行时常量池

run-time constant pool is a per-class or per-interface run-time representation of the constant_pool table in a class file (§4.4). It contains several kinds of constants, ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time. The run-time constant pool serves a function similar to that of a symbol table for a conventional programming language, although it contains a wider range of data than a typical symbol table.

基本概念

JVM 只有一个堆,且是被所有 JVM 线程共享的,类和数组等主要在堆中进行内存分配,堆的生命周期同样是与 JVM 互相绑定的。堆拥有以下特点:

  1. 堆是 Java 虚拟机锁管理内存中最大的一块,在虚拟机启动时创建,被所有线程共享
  2. Java 对象实例以及数组都在堆上分配
  3. 当堆无法满足内存分配需求时,将抛出 OOM 异常

虚拟机栈

  1. 虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态。换句话说,一个 Java 线程的运行状态,由一个虚拟机栈来保存,所以虚拟机栈肯定是线程私有的、独有的,随着线程的创建而创建
  2. 每一个线程执行的方法,为该栈中的栈帧,即每个方法的执行操作会对应一个栈帧
  3. 调用一个方法,就会向栈中压入一个栈帧;一个方法调用完成,就会把该栈帧从栈中弹出
image-1673510627413
image-1673510627413

以下异常情况与 Java 虚拟机堆栈相关联:

  • 栈帧数超过栈深会抛出 StackOverflowError 异常,如:无中断递归、无返回栈帧压入等
  • 如果 Java 虚拟机堆栈可以动态扩展,并且尝试扩展但没有足够的内存可用于实现扩展,或者如果没有足够的内存可用于为新线程创建初始 Java 虚拟机堆栈,则 Java 虚拟机将抛出 OutOfMemoryError 异常

栈帧

  1. 每个栈帧对应一个被调用的方法,可以理解为一个方法的运行空间
  2. 每个栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、动态链接(Dynamic Linking)、方法返回地址(Return Address)和附加信息

理解栈帧

通过 javap 指令得到反编译的字节码文件中一个方法的流程代表一个栈帧,一个栈帧中存放了 jvm 的指令

代码语言:javascript
复制
public static int calc(int, int);
	Code:
		0: iconst_3  // 将int类型常量3压入操作数栈
		1: istore_0  // 将int类型值存入局部变量0
		2: iload_0   // 从局部变量0中装载int类型值到操作数栈
		3: iload_1   // 从局部变量1中装载int类型值到操作数栈
		4: iadd      // 执行int类型的加法
		5: istore_2  // 将int类型值存入局部变量2
		6: iload_2   // 从局部变量2中装载int类型值
		7: ireturn   // 从方法中返回int类型的数据

程序计数器

基本概念

一个 JVM 进程中有多个线程正在执行,而线程中的内容是否能够拥有执行权,是根据 CPU 调度来的。

加入线程 A 正在执行到某个地方,突然失去了 CPU 的执行权,切换到了线程 B,然后当线程 A 再获得 CPU 执行权的时候,就需要通过线程中维护的一个变量来记录线程执行到哪个位置。程序计数器具有如下特点:

  1. 程序计数器占用的内存空间很小,由于 Java 虚拟机的多线程是通过线程轮流切换的,并分配处理器执行时间的方式来实现的,在任意时刻,一个处理器只会执行一条线程中的指令。因此,为了线程切换后能够恢复到正确的位置,每条线程需要有一个独立的程序计数器(线程私有)
  2. 如果线程正在执行 Java 方法,则计数器记录的是正在执行的虚拟机字节码指令的地址
  3. 如果正在执行的是 Native 方法,则这个计数器为空

本地方法栈

基本概念

如果当前线程执行的方法是 Native 雷晓宁的,这些方法就会在本地方法栈中执行,主要通过 C/C++ 来执行。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 运行时数据区
    • 官方解读
      • 方法区
        • 基本概念
        • 运行时常量池
        • 基本概念
      • 虚拟机栈
        • 栈帧
        • 理解栈帧
      • 程序计数器
        • 基本概念
      • 本地方法栈
        • 基本概念
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档