深入理解Java虚拟机:Java运行内存结构

news/2024/5/2 3:51:43/文章来源:https://blog.csdn.net/weixin_45187434/article/details/127700008

本篇内容包括:JAVA 运行内存结构,即 程序计数器、Java 虚拟机栈、本地方法栈 、Java堆、方法区、运行时常量池 以及 直接内存等相关内容!

一、JAVA 运行内存结构

Jvm 执行 Java 程序时,会把它所管理的内存划分为若干个不同的数据区域。

  • 其中一些数据区域是所有线程共享是,在 Jvm 启动时创建,在 Jvm 退出时销毁。如:方法区和堆。

  • 还有一些数据区域是每个线程独有的,在线程启动时创建,在线程结束时销毁。如:程序计数器、虚拟机栈和本地方法栈。

Java 虚拟机规范定义

下面介绍的是根据 Java 虚拟机规范定义的运行时数据区,单不同的虚拟机其运行时数据区定义也会有所不同。比如默认的 HotSpot 在实现 JDK1.7 虚拟机规范时,其常量池的定义不在方法区中,而是移到了堆中;到了 HotSpot JDK1.8 中,则彻底移除了持久代(方法区)而使用 Metaspace(元数据区)来进行替代等等。

JDK1.8 前后运行时数据区

二、线程独有数据区域(Java虚拟机规范定义的运行时数据区)

1、程序计数器

程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

  • 为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存;
  • 如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;
  • 如果正在执行的是 Native 方法,这个计数器值则为空(Undefined);
  • 程序计数器 是在 JVM 规范中,唯一一个没有规定任何 OutOfMemoryError 情况的区域(只存下一个字节码指令的地址,消耗内存小且固定,无论方法多深,它只存一条)。

2、Java 虚拟机栈

与程序计数器一样,Java 虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。

虚拟机栈描述的是 Java 方法执行的内存模型:每一个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

  • JVM 对栈的直接操作只有两个,方法执行时,进栈,执行结束后,出栈,所以对于栈不存在垃圾回收问题;
  • 栈中的数据都是以栈帧的格式存在,在这个线程上正在执行的每个方法都各自对应一个栈帧;
  • 不同线程中所有的栈帧是不允许存在相互引用的,即不可能在一个栈帧之中引用另一个线程的栈帧;
  • 如果当前方法调用了其他方法,方法返回之际,当前栈帧会传回此方法的执行结果给前一个栈帧,接着虚拟机会丢弃当前栈帧,使得前一个栈帧重新成为当前栈帧

参数设置:

  • -Xmx-MaxPermSize:设置栈可用的内存;

  • -Xss: 每个线程的堆栈大小,Jdk5.0 以后每个线程堆栈大小为 1M,以前每个线程堆栈大小为 256K,在相同物理内存下,减小这个值能生成更多的线程,但是操作系统对一个进程内的线程数还是有限制的,不能无限生成

在Java虚拟机规范中,对这个区域规定了两种异常状况:

  • 如果采用固定大小的Java虚拟机栈,那每个线程的Java虚拟机栈容量可以在线程创建时独立选定,如果线程请求分配的栈容量超过 Java 虚拟机栈允许的最大容量,将抛出 StackOverflowError 异常;
  • 如果虚拟机栈可以动态扩展(当前大部 分的Java虚拟机都可动态扩展,只不过 Java 虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛 OutOfMemoryError 异常。

3、本地方法栈

本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。在虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如 Sun HotSpo虚拟机)直接就把本地方法栈和虚拟机栈合二为一。

与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowErrorOutOfMemoryError 异常。


三、线程独有数据区域(Java虚拟机规范定义的运行时数据区)

1、Java堆

对于大多数应用来说,Java堆(Java Heap)是 Java 虚拟机所管理的内存中最大的一块。 Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做 GC堆(Garbage Collected Heap)。从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以 Java 堆中还可以细分为:新生代(Eden空间、From Survivor空间 和 To Survivor空间)、老年代、永久代(Hotspot虚拟机特有的概念,在 Java 8中,永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存——元空间 )等,不过这些区域划分仅仅是一部分垃圾回收器的红瞳特性或者说设计风格而已,而非某和 Java 虚拟机具体实现的固有的内存布局。

在Java 8中,永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存——元空间。

从内存分配的角度来看,线程共享的 Java 堆中可以划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB),以提升对象分配时的效率。不过无论从什么角度,无论如何划分,都不会改变 Java 堆中存储内容的共性,无论哪个区域,存储的都只能是对象的实例,进一步细分的目的是为了更好地回收内存,或者更快地分配内存。

参数设置:

根据Java虚拟机规范的规定,Java 堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)

  • -Xms:设置在JVM启动时的堆内存初始大小;

  • -Xmx:设置堆区允许的最大内存

如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常。

img

2、方法区

方法区(Method Area)与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被 Java 虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做 “非堆(Non-Heap)” ,目的应该是与 Java 堆区分开来。

说到方法区,不得不提一下“永久代”这个概念(方法区也称为“永久代”),这是因为垃圾回收器对方法区的垃圾回收比较少,主要是针对常量池的回收以及对类型的卸载,回收条件比较苛刻。经常会导致对此内存未完全回收而导致内存泄露,最后当方法区无法满足内存分配时,将抛出 OutOfMemoryError 异常。

参数设置:

  • -XX:Max-PermSize :设置指定的最大内存进行动态扩展。

3、运行时常量池

运行时常量池(Runtime Constant Pool)用于存放编译期生成的各种字面量和符号引用,是方法区的一部分。但是 Java 虚拟机规范对其没有做任何细节的要求,所以不同虚拟机实现商可以按照自己的需求来实现该区域,比如在 HotSpot 虚拟机实现中,就将运行时常量池移到了堆中。

Java 虚拟机对 .Class 文件每一部分(自然也包括常量池)的格式都有严格规定,每一个字节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可、装载和执行,但对于运行 时常量池,Java虚拟机规范没有做任何细节的要求,不同的提供商实现的虚拟机可以按照自己的需要来实现这个内存区域。不过,一般来说,除了保存 .Class 文件中描述的符号引用外, 还会把翻译出来的直接引用也存储在运行时常量池中。

运行时常量池相对于 .Class 文件常量池的另外一个重要特征是具备动态性,Java 语言并不要求常量一定只有编译期才能产生,也就是并非预置入 .Class 文件中常量池的内容才能进入方 法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是 String 类的 intern 方法。

既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时会抛出 OutOfMemoryError 异常。


四、直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规 范中定义的内存区域。但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError 异常出现,所以我们放到这里一起讲解。

在 Jdk1.4 中新加入了 NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓 冲区(Buffer)的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著 提高性能,因为避免了在Java堆和Native堆中来回复制数据。

显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,肯定还是 会受到本机总内存(包括RAM以及SWAP区或者分页文件)大小以及处理器寻址空间的限 制。

服务器管理员在配置虚拟机参数时,会根据实际内存设置 -Xmx 等参数信息,但经常忽略直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制), 从而导致动态扩展时出现 OutOfMemoryError 异常。

虚拟机内存与本地内存的区别:

Java 虚拟机在执行时会把内存分成不同的区域,这些区域被称为虚拟机内存。对于虚拟机没有直接管理的物理内存,我们称为本地内存,但这两种内存有一定的区别:

  • Jvm内存:受限于虚拟机内存大小的参数控制,当大小超过参数的设置时就会报 OOM 异常
  • 本地内存:本地内存不受虚拟机内存参数限制,只受物理机内存容量的限制。当超过物理机内存大小依然会报OOM异常。

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

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

相关文章

软件设计与体系——创建型模式

如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:瞳孔的个人空间 创建型模式: 创建型模式抽象了实例化过程帮助系统独立于如何创建、组合和表示对象 一个类创建型模式使用继承改变被实例化的类类创建型模式使用继承改变被实例化的类对象…

自学Python需要掌握哪些知识点?怎么学?

其实这个问题你可以转换一下思路,自学python有什么合适的学习路线,基本路线里涉及到的都是需要掌握的~ 单个知识点那罗列起来可是太多了~ 另外你可以考虑下你自学python的目的和方向,是单纯兴趣还是说要学了就业~ 想往人工智能方向发展还是P…

如何实现CAN/LIN通信路由测试?

目前车载网络通信越来越复杂,通信总线、协议多种多样,网关作为信息交互的载体,主要通过报文路由转发、报文过滤、信号重组等方式实现不同网段、不同协议间的信息交互;在复杂的车载网络中,网关通信路由转发功能具有非常…

软件设计师--数据结构考点细节总结

视频2022软件设计师-提炼高频考点-个人学习过程的总结,仅供参考!_哔哩哔哩_bilibili 目录 1,栈 2,二叉树 3,HUFFMAN 特点: 4,文件压缩比 5,拓扑排序 -- 有向无环图 6,查找 7…

CSDN编程竞赛第八期 | 参赛经历分享

参赛经历分享 一共参与七次了,这是我第二次在CSDN竞赛上获奖,上一次获奖是在第四期,获得了第三名,拿到了一个高级背包、一件T恤和一个获奖证书,我之前拍照发过动态的,详情请见:动态 - CSDN 然后…

机器视觉(三):摄像机标定技术

目录: 机器视觉(二):机器视觉硬件技术 机器视觉(三):摄像机标定技术 🌏🧐以下为正文🦄🪐 摄像机标定的目的:三维重建 空间物体表面…

FOTS:端到端的文本检测与识别方法的原理应用与优势

导言: 基于深度学习的可端到端训练的自然场景检测与识别算法(text spotting)由于其简洁高效且统一的结构,逐渐取代了过去将检测与识别分阶段训练然后拼接在一起的方案,成为自然场景文本检测与识别的主流研究方向之一。端到端自然场景文本检测…

rk3288-android8.1-OV13850

第一步,要到规格书,知道引脚定义 第二步,对应原理图定义 第三步 电源是打开的,如果是GPIO请设置 第四步,查看是否有驱动 out目录可以看到驱动 第五步,查看是否有以下文件

分组后再子集再查询

【问题】 有如下查询结果 从这里面查询每个产品 (ProductID) 具有某个(或同时具有某几个)属性 (即 AttID) 的产品数量,并按 ClassID 分组 如果只查询某个产品具有单个属性的话,可以用如下 SQL,如下面查询具有 AttID 为…

AI图像合成技术如何用于数字营销和创意领域?

全栈程序员推荐,AI好书必读 北大出版社,人工智能原理与实践 人工智能和数据科学从入门到精通 详解机器学习深度学习算法原理 人工智能原理与实践 全面涵盖人工智能和数据科学各个重要体系经典 “哇,你拍到的吗?等一下——那是专…

Ray 框架

一 Ray是什么,优势 Spark则是一个面向数据处理的产品,RDD则是以数据作为抽象对象的,你关心的应该是数据如何处理,而不是去如何拆解任务,关心资源如何被分配,这其中涉及的概念比如Job,Stage,task你最好都不…

1807521-02-3,PEP azide,PEP叠氮化物其中叠氮基发生点击反应

PEP azide叠氮基在铜存在下与炔烃反应,生成三唑,可作为多功能连接物。西安凯新生物科技有限公司​叠氮基可以通过点击化学与炔烃、BCN、DBCO反应,生成稳定的三唑键。末端羧酸在活化剂(如EDC或HATU)存在下可与伯胺基反应…

【数据结构与算法】详解归并

目录一、归并的定义及思路二、归并的代码实现一、归并的定义及思路 归并就是归并排序,将两个有序的或两个以上有序的数列合并成一个有序的数列 其基本思想是: 分而治之,与快排的分治是不同的,并归是以中间点分治。 其步骤为&#…

web自动化测试入门篇02——selenium安装教程

😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。 📡主页地址:【Austin_zhai】 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。…

查题校园题库

查题校园题库 本平台优点: 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 查题校园题库:查题校园题库后台(点击跳转&a…

视频去水印免费软件有哪些?快来收藏这三款实用工具

大家平时在追剧时,会提前下载视频再去观看吗?我就会这样做,因为有时候看着看着,就会出现网络卡顿的问题。不过下载后的视频经常会打上平台的水印,特别影响观感。因此很多小伙伴会去寻找去除视频水印的软件。今天正好做…

回溯算法题目

文章目录1.lc77 组合2.lc216 组合总和 III3.lc17 电话号码的字母组合4.lc39 组合总和5.lc40 组合总和 II6. lc131 分割回文串1.lc77 组合 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 https://leetcode.cn/p…

mybatis 自动化处理 mysql 的json类型字段 终极方案

文章目录mybatis 自动化处理 mysql 的json类型字段 终极方案mysql 建表 json 字段,添加1条json 数据对应的java对象 JsonEntitymybatis,不使用 通用mapper手动自定义1个类型处理器,专门处理 JsonNode 和Json 的互相转化将 自定义的类型处理器…

C/C++微实践 - 发现圆周率

除了祖冲之的割圆法和格雷戈里公式,借助于循环和随机数,我们还可以通过一种特别有趣的方法来估算圆周率。 本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔 叔"&#…

vue3 组件响应式v-model 失效,实践踩坑,一文搞懂组件响应式原理,对初学者友好

文章目录前情提要实战解析最后前情提要 vue3的v-model已经有了变化,假如你还不知道其中细节,看完这篇文章你就完全明白了,我以踩坑的场景来进行解析。起因是在我的项目中需要一个输入框组件,这个组件用来根据输入异步查询系统内已…