JVM运行时数据区(Run-Time Data Areas) - Java内存分配

本文详细介绍了Java虚拟机(JVM)的六大数据区域,包括程序计数器(PC)寄存器、JVM堆栈、本机方法堆栈、堆、方法区域和运行时常量池。解释了每个区域的作用、线程间的共享方式以及可能引发的异常情况。

译文链接
Java虚拟机(JVM)定义了在程序执行期间使用的各种运行时数据区域。其中一些JVM数据区域是按线程创建的,而其他JVM数据区域是在JVM启动时创建的,而内存区域是在线程之间共享的。

根据使用情况,JVM运行时数据区域可分为六个区域

  • 程序计数器(PC)寄存器
  • Java虚拟机(JVM)堆栈
  • 本机方法堆栈
  • 方法区域
  • 运行时常量池

如上所述,这些记忆区域可分为两类 -

每个线程创建 - PC寄存器,JVM堆栈,本机方法堆栈
由线程共享 - 堆,方法区域,运行时常量池

在这里插入图片描述

JVM运行时数据区

1.程序计数器(PC)寄存器 - 在任何给定时间的JVM中,许多线程可能正在执行。每个执行线程都有自己的PC寄存器。
如果JVM线程执行的方法是JAVA方法,则PC寄存器包含当前正在执行的Java虚拟机指令的地址。如果线程正在执行本机方法,则Java虚拟机的pc寄存器的值是未定义的。

2.Java虚拟机(JVM)堆栈 - 每个JVM线程都有自己的JVM堆栈,该堆栈在线程启动时创建。JVM堆栈存储从堆栈中推出和弹出的帧,永远不会直接操作JVM堆栈。
在任何异常时,您将获得此堆栈跟踪,其中每个元素表示单个堆栈帧。

与Java虚拟机堆栈相关的特殊条件:
如果线程中的计算需要比允许的更大的Java虚拟机堆栈,则Java虚拟机会抛出StackOverflowError。
如果可以动态扩展Java虚拟机堆栈,并且尝试进行扩展但可以使内存不足以实现扩展,或者可以使内存不足以为新线程创建初始Java虚拟机堆栈,则Java Virtual机器抛出OutOfMemoryError。

JVM堆栈中的帧
调用方法时会创建一个新帧,然后将该帧推送到该线程的JVM堆栈中。当方法调用完成时,框架将被销毁。
每个帧都有自己的局部变量数组,它自己的操作数堆栈以及对当前方法类的运行时常量池的引用。局部变量数组和操作数堆栈的大小在编译时确定,并与用于与帧相关联的方法的代码一起提供。

在任何时候只有一个帧是活动的,这是执行方法的帧。该帧被称为当前帧,并且其方法被称为当前方法。定义当前方法的类是当前类。

请注意,由线程创建的帧对于该线程是本地的,并且不能被任何其他线程引用。

  • 局部变量 - 创建并添加到JVM堆栈的每个帧都包含一个称为局部变量的变量数组。
    局部变量数组的长度在编译时自身确定,并以类或接口的二进制表示形式提供,同时提供与帧相关的方法的代码。
    调用方法时,JVM使用局部变量传递参数。
    如果是类方法,则从局部变量0开始,在连续的局部变量中传递任何参数。
    如果它是一个实例方法,则局部变量0总是用于传递对调用实例方法的对象的引用,即this。随后,任何参数都在从局部变量1开始的连续局部变量中传递。

  • 操作数堆栈 - 每个帧包含一个后进先出(LIFO)堆栈,称为帧的操作数堆栈。操作数堆栈的最大深度称为编译时间本身,并随与帧相关的方法的代码一起提供。
    操作数堆栈是方法执行时的实际存储位置。为方法创建帧时,其操作数堆栈为空。Java虚拟机将提供指令,以将局部变量或字段中的常量或值加载到操作数堆栈中。其他JVM指令从操作数堆栈中获取操作数,对它们进行操作,并将结果推回操作数堆栈。
    操作数堆栈还用于准备要传递给方法和接收方法结果的参数。

  • 执行动态链接 - 在已编译的.class文件中,方法的代码是指要调用的方法和要通过符号引用访问的变量。这些符号方法引用通过动态链接转换为具体方法引用,根据需要加载类以解析符号那时尚未定义。
    JVM堆栈中的每个帧都包含对当前方法类型的运行时常量池的引用,以支持方法代码的动态链接。

3.本机方法堆栈 - JVM也可以使用传统堆栈以支持本机方法。本机方法是用Java编程语言以外的语言编写的方法。
在创建每个线程时,每个线程都会分配本机方法堆栈。

以下异常条件与本机方法堆栈相关联:

如果线程中的计算需要比允许的更大的本机方法堆栈,则Java虚拟机会抛出StackOverflowError。
如果可以动态扩展本机方法堆栈并尝试本机方法堆栈扩展但可用内存不足,或者如果可用内存不足以为新线程创建初始本机方法堆栈,则Java虚拟机会抛出OutOfMemoryError。
4.
堆是JVM运行时数据区,内存从该数据区分配给对象,实例变量和数组。堆是在JVM启动时创建的,并在所有Java虚拟机线程之间共享。
一旦存储在堆上的对象没有任何引用,该对象的内存就由垃圾收集器回收,垃圾收集器 是一个自动存储管理系统。永远不会明确释放对象。

以下异常情况与堆相关联:

如果计算需要的堆数超过自动存储管理系统可用的堆,则Java虚拟机会抛出OutOfMemoryError。
请参阅Java中的堆内存分配以了解有关堆内存分配以及如何在此处收集垃圾的更多信息

5.方法区域 - JVM具有在所有JVM线程之间共享的方法区域。方法区域存储有关已加载的类和接口的元数据。它存储每类结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码。
存储在方法区域中的类型信息由JVM加载的每种类型如下 -

  • 类/接口的完全限定名称。
  • 任何直接超类的完全限定名称。
  • 使用的修饰符。
  • 任何扩展超级接口的完全限定名称。
  • 用于区分加载类型是类还是接口的信息。

除了类型信息方法区域还存储

  • 运行时常量池
  • 字段信息,包括字段名称,类型,修饰符。
  • 方法信息,包括方法名称,修饰符,返回类型,参数。
  • 静态(类)变量。
  • 方法代码包含字节代码,局部变量大小,操作数堆栈大小。

方法区域通常是非堆内存的一部分,以前称为PermGen空间。请注意, PermGen Space从Java 8更改为MetaSpace。

请参阅Java 8中的PermGen Space Removal以了解有关Java 8中MetaSpace的更多信息。
以下异常条件与方法区域相关联:

如果无法使方法区域中的内存满足分配请求,则Java虚拟机将抛出OutOfMemoryError。
6. 运行时常量池
运行时常量池是类的constant_pool表的每类或每个接口存储。Constant_pool包含在编译时已知的常量(字符串文字,数字文字),它还存储必须在运行时解析的方法和字段引用。
运行时常量池在线程之间共享,并从JVM的方法区域分配。

不是将所有内容存储在字节代码中,而是为类维护单独的常量池,字节代码包含对常量池的引用。这些符号引用通过动态链接转化为具体的方法参考。

例如 - 这是一个字节代码片段 -

0 :aload_0
1 :invokespecial #1 //方法java / lang / Object。“”?)V 4 :aload_0
5 :new #2 // class javafx / beans / property / SimpleStringProperty

如果你注意到这里invokespecial operand有一个前缀#1,这个数字(#1)引用存储实例初始化方法的常量池。

第5行中的新Opcode后面跟着编号#2。这意味着引用常量池中的第二个索引。

以下异常条件与类或接口的运行时常量池的构造相关联:

创建类或接口时,如果运行时常量池的构造需要的内存比Java虚拟机的方法区域中可用的内存多,则Java虚拟机会抛出OutOfMemoryError。

内容概要:本文是一篇关于使用RandLANet模型对SensatUrban数据集进行点云语义分割的实战教程,系统介绍了从环境搭建、数据准备、模型训练与测试到精度评估的完整流程。文章详细说明了在Ubuntu系统下配置TensorFlow 2.2、CUDA及cuDNN等深度学习环境的方法,并指导用户下载和预处理SensatUrban数据集。随后,逐步讲解RandLANet代码的获取与运行方式,包括训练、测试命令的执行与参数含义,以及如何监控训练过程中的关键指标。最后,教程涵盖测试结果分析、向官方平台提交结果、解读评估报告及可视化效果等内容,并针对常见问题提供解决方案。; 适合人群:具备一定深度学习基础,熟悉Python编程和深度学习框架,从事计算机视觉或三维点云相关研究的学生、研究人员及工程师;适合希望动手实践点云语义分割项目的初学者与进阶者。; 使用场景及目标:①掌握RandLANet网络结构及其在点云语义分割任务中的应用;②学会完整部署一个点云分割项目,包括数据处理、模型训练、测试与性能评估;③为参与相关竞赛或科研项目提供技术支撑。; 阅读建议:建议读者结合提供的代码链接和密码访问完整资料,在本地或云端环境中边操作边学习,重点关注数据格式要求与训练参数设置,遇到问题参考“常见问题与解决技巧”部分及排查。
内容概要:本文详细介绍了三相异步电机SVPWM-DTC(空间矢量脉宽调制-直接转矩控制)的Simulink仿真实现方法,结合DTC响应快与SVPWM谐波小的优点,构建高性能电机控制系统。文章系统阐述了控制原理,包括定子磁链观测、转矩与磁链误差滞环比较、扇区判断及电压矢量选择,并通过SVPWM技术生成固定频率PWM信号,提升系统稳态性能。同提供了完整的Simulink建模流程,涵盖电机本体、磁链观测器、误差比较、矢量选择、SVPWM调制、逆变器驱动等模块的搭建与参数设置,给出了仿真调试要点与预期结果,如电流正弦性、转矩响应快、磁链轨迹趋圆等,并提出了模型优化与扩展方向,如改进观测器、自适应滞环、弱磁控制和转速闭环等。; 适合人群:电气工程、自动化及相关专业本科生、研究生,从事电机控制算法开发的工程师,具备一定MATLAB/Simulink和电机控制理论基础的技术人员。; 使用场景及目标:①掌握SVPWM-DTC控制策略的核心原理与实现方式;②在Simulink中独立完成三相异步电机高性能控制系统的建模与仿真;③通过仿真验证控制算法有效性,为实际工程应用提供设计依据。; 阅读建议:学习过程中应结合文中提供的电机参数和模块配置逐步搭建模型,重点关注磁链观测、矢量选择表和SVPWM调制的实现细节,仿真注意滞环宽度与开关频率的调试,建议配合MATLAB官方工具箱文档进行参数校准与结果分析。
已经博主授权,源码转载自 https://pan.quark.cn/s/bf1e0d5b9490 本文重点阐述了Vue2.0多Tab切换组件的封装实践,详细说明了通过封装Tab切换组件达成多Tab切换功能,从而满足日常应用需求。 知识点1:Vue2.0多Tab切换组件的封装* 借助封装Tab切换组件,达成多Tab切换功能* 支持tab切换、tab定位、tab自动化仿React多Tab实现知识点2:TabItems组件的应用* 在index.vue文件中应用TabItems组件,借助name属性设定tab的标题* 通过:isContTab属性来设定tab的内容* 能够采用子组件作为tab的内容知识点3:TabItems组件的样式* 借助index.less文件来设定TabItems组件的样式* 设定tab的标题样式、背景色彩、边框样式等* 使用animation达成tab的切换动画知识点4:Vue2.0多Tab切换组件的构建* 借助运用Vue2.0框架,达成多Tab切换组件的封装* 使用Vue2.0的组件化理念,达成TabItems组件的封装* 通过运用Vue2.0的指令和绑定机制,达成tab的切换功能知识点5:Vue2.0多Tab切换组件的优势* 达成多Tab切换功能,满足日常应用需求* 支持tab切换、tab定位、tab自动化仿React多Tab实现* 能够满足多样的业务需求,具备良好的扩展性知识点6:Vue2.0多Tab切换组件的应用场景* 能够应用于多样的业务场景,例如:管理系统、电商平台、社交媒体等* 能够满足不同的业务需求,例如:多Tab切换、数据展示、交互式操作等* 能够与其它Vue2.0组件结合运用,达成复杂的业务逻辑Vue2.0多Tab切换组件的封装实例提供了...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值