JVM-运行时数据区

目录

什么是运行时数据区?

方法区

程序计数器

虚拟机栈

局部变量表    

操作数栈       

动态连接

运行时常量池

方法返回地址

附加信息

本地方法栈

总结:


什么是运行时数据区?

     Java虚拟机在执行Java程序时,将它管理的内存分为不同的区域。这些区域用途不同,创建和销毁的时间也不同。有的随虚拟机进程启动一直存在,有的依赖用户线程启动和结束而创建和销毁。根据《Java虚拟机规范》,Java虚拟机管理的内存区域包括以下几个运行时数据区域。

来自《深入理解Java虚拟机(第3版)》

方法区

        方法区用于存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。可以理解为被线程共享的内存区域。
         根据《Java虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出
OutOfMemoryError异常。

        Java堆(Java heap)是虚拟机管理的最大一块内存,线程共享,虚拟机启动时创建,用于存储对象实例。虽然在《Java虚拟机规范》中对Java堆的描述是:“所有 的对象实例以及数组都应当在堆上分配”,但随着即时编译技术的发展,栈上分配,标量替换等优化手段,Java实例不仅仅分配在堆上。

        Java堆是垃圾回收的主要区域,HotSpot VM 的堆内存又分为新生代、老年代和永久代。新生代又分为Eden空间和Survivor空间。 常见的垃圾收集器也都是围绕这些内存区域进行工作的。将Java堆细分,主要是为了更好的回收内存或更快分配内存。

        根据《Java虚拟机规范》的规定,Java堆可以处于物理上不连续的内存空间中,但在逻辑上应是连续的,就像我们使用磁盘空间存储文件一样,并不要求所有文件连续存放。但对于大对象(典型的如数组对象),多数虚拟机实现出于实现简单、存储高效的考虑,很可能会要求连续的 内存空间。

        Java堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的Java虚拟机都是按照可扩展来实现的(通过参数-Xmx和-Xms设定)。如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。

程序计数器

      因为Java虚拟机中的多线程通过线程轮流切换、分配处理器的执行时间的方式实现,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。为了在线程切换后准确恢复到正确的执行位置,需要记录每个线程的所执行的字节码的行号,这时就需要程序计数器。

      程序计数器是一块较小的内存,每个线程都需要一个独立的程序计数器,每个线程之间程序计数器互不影响,独立存储,是“线程私有”的内存。在Java虚拟机的概念模型里,通过改变程序计数器的值选取下一条需要执行的字节码指令。程序计数器,是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础都需要依赖这个计数器完成。大家会想到程序在计算机上执行过程中的程序技术器,决定着程序执行的流程。

       如果执行的是本地(Native)方法,程序计数器的值则应为空(undefined),此区域是为一个一个在《Java虚拟机规范》中没有任何OutOfMemeoryError情况的区域

虚拟机栈

        Java虚拟机栈,也是线程私有的,和线程的生命周期相同。

        每个方法被执行时,Java虚拟机会同步创建一个栈帧,每个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中刚从入栈到出栈的过程。

栈帧由几部分组成?

      局部变量表,操作数栈,方法返回地址,动态连接,附加信息等。

局部变量表    

        我们知道方法由:访问修饰符(可选),返回值,方法名,参数列表,方法体组成。

        局部变量表,保存方法参数和方法内部的局部变量,在局部变量表中的存储空间以变量槽(slot)为单位,每个槽都应该能存放一个boolean,byte,char,short,int,float,reference或returnAddress类型的数据,这8种数据类型都可以使用32位或更小的物理内存累存储,且随着处理器、操作系统或虚拟机实现的不同而发生变化。局部变量表的空间在编译期即可根据源码和虚拟机的具体栈内存实现方式确定,不会受程序运行时数据的影响。

操作数栈       

        操作数栈,是一个先进后出的栈结构,用于临时保存方法执行过程的操作数。比如在进行加法运算:1+2=3时。

1. 将第一个操作数 1 压入操作数栈;

2. 将第二个操作数 2 压入操作数栈;

3. 从操作数栈弹出第二个操作数 2;

4. 从操作数栈弹出第一个操作数 1;

5. 将两个操作数相加得到结果 3;

6. 将结果 3 压入操作数栈;

7. 从操作数栈弹出结果 3;

       通过操作数栈,虚拟机可以方便地对运算中的操作数进行入栈和出栈,实现复杂的算术运算逻辑。它避免了每次运算都需要在堆内存中分配新的操作数对象,可以提高执行效率。高效地对方法运算过程中的操作数进行入栈出栈操作,这是实现Java虚拟机高效运行的重要组成部分。每个栈帧的操作数栈的深度,在编译器也可确定,在运行期间不会变。

动态连接

        在讲动态连接之前,我们先回顾一下运行时常量池的知识。

运行时常量池

        运行时常量池位于方法区。Class文件中除了有类的版本、字段、方法、接口等描述信息,还有一项是常量池表,用于存放编译期生成的各种字面量和符号引用,常量池表中这部分内容将在类加载后存放在方法区的常量池中,运行期间也可以将新的常量放到常量池中。

        Class文件的常量池中存在大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或者第一次使用的时候被转为直接引用,这种转化被称为静态解析。另一部分将在每次运行期间都转化为直接引用,这部分称为动态连接。

        动态连接是指在程序运行时才去解析字节码中的符号引用,并把符号引用替换为直接引用的过程,主要为了支持Java动态绑定机制。动态绑定允许程序运行时才去决定实际调用的方法,给Java带来很大的灵活性,支持Java的多态特性。

举个例子:

public class Main {
  public static void main(String[] args) {
    Animal a = new Dog(); 
    a.run();
  }
}

class Animal {
  public void run() {
    System.out.println("Animal is running");
  }
}

class Dog extends Animal {
  @Override
  public void run() {
    System.out.println("Dog is running"); 
  }
}

        编译时,编译器只知道a是一个Animal对象,它不知道a最终会指向一个Dog对象。

        运行时,JVM通过动态连接,才会根据实际的对象类型Dog,动态地绑定到Dog.run()这个方法上,从而输出"Dog is running"。如果没有动态连接,那么只能静态地绑定到Animal.run(),就无法利用多态的特性了。所以动态连接是支持运行时多态以及动态绑定的关键。它让Java语言可以更灵活地处理对象的多态特性。       

方法返回地址

        方法执行完退出时,无论是遇到方法返回的字节码指令还是遇到异常退出,都需要返回到最初方法被调用的位置,程序才能继续执行。这个位置就是方法返回地址。

例如:

public int sum(int a, int b) {
  return a + b;
}

public static void main(String[] args) {
  int s = sum(1, 2);
  System.out.println(s);
}

        在main方法调用sum方法时,会先记录下 “int s = sum(1,2);” 这行代码的位置,当sum方法执行完返回结果后,返回到该位置,执行后面的“System.out.pringln(s);”方法。所以,方法返回地址,就是调用该方法的具体代码位置。

        JVM通过动态连接找到方法的入口,并记录下返回地址,以便在方法执行后正确返回到调用方。返回地址是实现正确的方法调用流程所必需的。动态连接使得返回地址可以在运行时确定,这样Java程序才可以实现动态绑定和灵活的函数调用机制。 

        而方法返回后,该方法对应的栈帧会出栈,栈顶的栈帧就是该方法的调用者,调用者的局部变量表可能会发生变化,这取决于方法的返回值是否被赋值给了调用者栈帧的某个局部变量。还以上面的方法为例,当sum方法执行完返回后,main方法栈帧的局部变量s被赋值为sum方法的返回值3。

附加信息

        附加信息,是指在进行方法调用时,除了明确的参数和返回值之外,还可以传递的一些额外信息。从理论上讲,它提供了一种传递方法调用的额外上下文的方式,对JVM内部来说可以提供更多信息。一些专业的程序分析和追踪工具可能会用到它们,对日常开发影响不大。

本地方法栈

        本地方法栈(Native Method Stack):与虚拟机栈类似,用于支持Native方法的执行。关于本地方法,可参考Java本地方法/Java native方法/JNI_jni native方法_小王师傅66的博客-CSDN博客

总结:

        JVM运行时数据区主要包括:方法区,堆,虚拟机栈,程序计数器,本地方法栈。

        方法区(Method Area):用于存储类信息、静态变量、静态方法等数据,可以理解为所有线程共享的内存区域。方法区无法满足新的内存分配需求时,会抛出OutOfMemeoryError异常;
        堆内存(Heap):用于存储对象实例,可以理解为所有线程共享的内存区域。如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。可以通过调整-Xms和-Xmx参数调整堆空间;
        虚拟机栈(VM stack):用于存储局部变量表、操作栈、动态链接、方法返回地址/方法出口等信息,属于线程私有。每个线程都有自己的虚拟机栈。当线程请求的栈深度超过虚拟机所允许的最大深度时,就会抛出 StackOverflowError 异常。当虚拟机栈的空间无法分配时,将抛出 OutOfMemoryError 异常。可以通过调整-Xss参数调整栈空间;
        程序计数器(PC Register):用于存储指向下一条将要执行的指令的地址,每个线程都有自己的程序计数器,它的空间是非常小的,基本不会发生溢出的情况。
        本地方法栈(Native Method Stack):与虚拟机栈类似,用于支持Native方法的执行。本地方法栈也是线程私有,与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/56122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

张量Tensor 深度学习

1 张量的定义 张量tensor理论是数学的一个分支学科,在力学中有重要的应用。张量这一术语源于力学,最初是用来表示弹性介质中各点应力状态的,后来张量理论发展成为力学和物理学的一个有力数学工具。 张量(Tensor)是一个…

6.s081(Fall 2022)Lab2: system calls

文章目录 前言其他篇章参考链接0. 前置准备1. System call tracing (moderate) 前言 好像没啥前言 其他篇章 环境搭建 Lab1:Utilities 参考链接 官网链接 xv6手册链接,这个挺重要的,建议做lab之前最好读一读。 xv6手册中文版,这是几位先…

ATFX汇市:惠誉下调美债评级,白宫债务无序扩张下,美元国际信用受损

环球汇市行情摘要—— 昨日,美元指数上涨0.06%,收盘在101.94点, 欧元贬值0.12%,收盘价1.0984点; 日元贬值0.75%,收盘价143.33点; 英镑贬值0.46%,收盘价1.2776点; 瑞…

模电专题-MOS管的放大电路分析

在实际应用中,我们经常会使用到功率MOS,这时通常不会将它当成一个开关使用,而是当成一个放大器来使用,那这就需要让其工作在放大状态。 参考下图中的mos管的特性曲线,右图中的输出特性曲线中有一根红色的分界线&#x…

python基础2——数据类型

文章目录 一、字符串处理1.1 占位符1.2 拼接符1.3 统计字符串长度1.4 切片取值1.5 内置字符串处理方法 二、组合数据类型2.1 列表2.2 元组2.3 集合2.4 字典 三、数据类型转换 一、字符串处理 1.1 占位符 可以使用%s占位符在字符串中引用变量。 1.有两种写法。 name "qi…

AP5179 高端电流采样降压恒流驱动IC SOP8 LED车灯电源驱动

产品描述 AP5179是一款连续电感电流导通模式的降压恒流源,用于驱动一颗或多颗串联LED输入电压范围从 5 V 到 60V,输出电流 最大可达 2.0A 。根据不同的输入电压和外部器件, 可以驱动高达数十瓦的 LED。内置功率开关,采用高端电流…

【Claude2体验】继ChatGPT,文心一言,Bing等大模型后,初次对话Claude2的体验

文章目录 🌺注意事项🤖什么是Claude2⭐与之前版本的进步🛸官网的讲解🍔功能介绍🎄使用体验🎆查看不知道如何才能打开的文档 的内容🎆日常需求✨Claude✨ChatGPT3.5 🤖总结 &#x1f…

【Linux命令200例】split将一个大文件拆分成多个小文件

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主✌,2023年6月csdn上海赛道top4✌。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加…

Windows下FreeImage库的配置

首先下载FreeImage库,http://freeimage.sourceforge.net/download.html,官网下载如下: 内部下载地址:https://download.csdn.net/download/qq_36314864/88140305 解压后,打开FreeImage.2017.sln,如果是vs…

springboot参数校验

springboot参数传递 PathVariableRequestParamRequestBody JSR303 jsr303 : 也称 bean validation 规范,用于java bean 验证的标准API,,他定义了一组注解,可以在javabean 的属性上声明验证规则 JSR: ja…

微信公众号开发学习

申请测试号 地址 通过F12抓取体验接口权限表的HTML 解析HTML 引入pom <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><…

127.【SpringBoot 源码刨析D】

SpringBoot 源码刨析D (三)、SpringBoot 核心功能4.单元测试功能(1).JUnit5 的变化(2).JUnit5常用注解(3).断言&#xff08; assertions &#xff09;(3.1).简单断言(3.2).数组断言(3.3).组合断言(3.4).异常断言(3.5).超时断言(3.6).快速失败 (4).前置条件&#xff08; assumpt…

SpringBoot集成MyBatisPlus+MySQL(超详细)

前言 查看此文章前强烈建议先看这篇文章&#xff1a;Java江湖路 | 专栏目录 该文章纪录的是SpringBoot快速集成MyBatis Plus&#xff0c;每一步都有记录&#xff0c;争取每一位看该文章的小伙伴都能操作成功。达到自己想要的效果~ 文章目录 前言1、什么是MyBatisPlus2、Spring…

JetBrains 为测试自动化打造的强大 IDE-Aqua

QA 和测试工程对现代软件开发必不可少。 在 JetBrains&#xff0c;我们相信使用正确的工具对每项工作都很重要。 对我们来说&#xff0c;为自动化测试开发创建单独的工具是自然而然的事&#xff0c;因为这使我们能够满足多角色软件开发团队的需求。 我们很高兴能够推出 JetBra…

Windows下RocketMQ的启动

下载地址&#xff1a;下载 | RocketMQ 解压后 一、修改runbroker.cmd 修改 bin目录下的runbroker.cmd set "JAVA_OPT%JAVA_OPT% -server -Xms2g -Xmx2g" set "JAVA_OPT%JAVA_OPT% -XX:MaxDirectMemorySize15g" set "JAVA_OPT%JAVA_OPT% -cp %CLASSP…

给你一个小技巧,解放办公室管理!

电力的稳定供应对于现代社会中的办公室和企业来说至关重要。为了应对这些潜在的问题&#xff0c;许多办公室和企业都采用了不间断电源&#xff08;UPS&#xff09;系统来提供电力备份。UPS可以保持关键设备的运行&#xff0c;确保生产和业务不受干扰。 然而&#xff0c;仅仅安装…

C# Blazor 学习笔记(0.1):如何开始Blazor和vs基本设置

文章目录 前言资源推荐环境如何开始Blazor个人推荐设置注释快捷键热重载设置 前言 Blazor简单来说就是微软提供的.NET 前端框架。使用 WebAssembly的“云浏览器”&#xff0c;集成了Vue,React,Angular等知名前端框架的特点。 资源推荐 微软官方文档 Blazor入门基础视频合集 …

NO4 实验四:生成Web工程

1、说明 使用 mvn archetype&#xff1a;generate 命令生成 Web 工程时&#xff0c;需要使用一个专门的 archetype。这个专门生成 Web 工程骨架的 archetype 可以参照官网看到它的用法&#xff1a; 2、操作 注意&#xff1a;如果在上一个工程的目录下执行 mvn archetype&…

​LeetCode解法汇总142. 环形链表 II

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a; 力扣 描述&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如…

Spring Boot配置文件

hi,大家好,今天为大家带来Spring Boot 的配置文件相关的知识 文章目录 &#x1f437;上期遗留问题:约定大于配置:&#x1f96b;1.配置文件作用&#x1f96b;2.配置文件格式&#x1f96b;3.properties配置文件介绍&#x1f367;3.1properties基本语法&#x1f367;3.2 读取配置…