当前位置: 首页 > news >正文

JVM面试(二)内存区域划分

内存区划分

Java虚拟机在执行Java程序的过程中会把它锁管理的内存划分为若干个不同的数据区域。 这些区域有各自不同的用途,以及创建和销毁的时间。 有的区域随着虚拟机的进程一直存在,有的区域依赖用户线程的启动和结束而建立和销毁。

根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存,包含一下几个运行时的数据区域。如图:

在这里插入图片描述

一般我们面试的时候,都是笼统的说:堆、栈、以及方法区,JDK 8之后方法区变为“元空间”。
这个说法不错,下面我们详解一下。

程序计数器

程序计数器区域⼀块内存较小的区域,它⽤于存储线程的每个执行指令,每个线程都有自己的程序计数器,此区域不会有内存溢出的情况。
由于Java虚拟机的多线程是通过线程的轮流切换、分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都只执行一个线程。
那么为了每次切换线程后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器, 所以这个程序计数器区域,是一个线程私有的内存。

虚拟机栈与本地线程栈

在很多情况下,我们都是把这两个合在一起说的。
两方面的原因,一个是《Java虚拟机规范》对本地方法栈使用的语言、使用方式等没有任何规定。 二是有些虚拟机确实把这两个合二为一,比如Hot-Spot虚拟机。

如果按照我这里的浅显理解的话,他们之间的区别可以这么说。
虚拟机栈的生命周期与线程相同,主要就是存储线程执行相关的局部变量信息。
本地方法栈也是如此,但是所执行的内容可能是虚拟机本地方法Native。

所以我们在面试的时候,可以只说虚拟机栈,甚至直说本地方法栈都可以。(在我面试数十次的经历中,确实没有遇到,挑这两个问区别的)

回到虚拟机栈,在每个方法被执行的时候,Java虚拟机都会在这个线程栈中创建一个“栈帧”,用于存储局部变量表,操作数栈,方法出口等等信息。每一个方法被调用,直到执行完毕,就对应着一个栈帧从入栈到出栈的过程。

因为我们线程调用方法是一层层递进的,所以这个栈帧也是一层层叠加。当调用深度超过虚拟机所允许的深度时,就会抛出StackOverflowError异常。

还有一个情况是,栈帧层层递进的时候,虚拟机栈也是在不断增大。
如果栈的内存不足,并且提前分配好不能扩展;或者是扩展的时候无法申请到足够的内存,就会发生OutOfMemoryError异常。

堆区

堆区是各个线程共享的区域。
这也是老生常谈的问题,主要存放JVM启动时创建的数组和对象实例,还有垃圾回收也主要在堆区发生,还有分代模型等等巴拉巴拉。
具体内容我们可以到分析垃圾回收的时候详细说下。
需要注意的是,堆区也是可以被固定大小的,当内存不足无法扩展时,也会抛出OutOfMemoryError异常。

方法区

与堆区一样,也是各个线程共享的区域。
主要存储那些常亮,静态变量,代码缓存等数据。虽然《Java虚拟机规范》中把方法区描述为一个堆区的逻辑部分,但是名字却为“Non-Heap” 非堆,这就是要与堆区做区分。

这里不得不提一下“永久代” 这个概念,以前很多时候都是把永久代与方法区混为一谈。
这是因为HotSpot虚拟机的设计团队把垃圾收集器的分代设计扩展到了方法区,把方法区称为永久代来管理垃圾回收机制。

但是后来又把永久代的概念放到了本地内存中,一直到JDK8 之后,完全放弃了永久代的概念,改为在本地内存新实现的“元空间”来代替

粗略来说,就是最早时候方法区=永久代,后来统一并入本地内存的“元空间”中。

运行时常量池

也是方法区的一部分,主要 存储Class文件中编译期生成的各种字面量与符号引用

字面量是源代码中的固定值的表示法,即通过字面我们就能知道其值的含义。字面量包括整数、浮点数和字符串字面量;

符号引用包括类符号引用、字段符号引用、方法符号引用和接口方法符号引用。符号引用就是⼀个字符串,只要我们在代码中引用了⼀个非字面量的东西,不管它是变量还是常量,它都只是由⼀个字符串定义的符号,这个字符串存在常量池里,类加载的时候第一次加载到这个符号时,就会将这个符号引用(字符串)解析成直接引用(指针)。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 在MySQL存储过程中,以下句子需要以分号(;)结尾
  • 后台框架-统一数据格式
  • 网站建设完成后, 做seo必须知道的专业知识之--蜘蛛陷阱
  • 如何防范ddos 攻击
  • 二分查找精炼回顾-kevin
  • 在线压缩pdf,无需安装就可轻易压缩pdf文件
  • Axure RP下载+详细安装步骤资源百度云盘分享
  • Flask框架 完整实战案例 附代码解读 【3】
  • 【CSS】如何写渐变色文字并且有打光效果
  • OceanBase V4.2解析:如何用迭代器 Generator快速生成任意数据
  • DS18B20温度传感器详解(STM32)
  • MySQL基础学习:MySQL主从复制如何实现
  • 在HarmonyOS中灵活运用Video组件实现视频播放
  • Golang | Leetcode Golang题解之第385题迷你语法分析器
  • Level3 — PART 4 机器学习算法 — 集成学习
  • [iOS]Core Data浅析一 -- 启用Core Data
  • ECMAScript6(0):ES6简明参考手册
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • ReactNative开发常用的三方模块
  • Travix是如何部署应用程序到Kubernetes上的
  • 创建一种深思熟虑的文化
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 我从编程教室毕业
  • 物联网链路协议
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 主流的CSS水平和垂直居中技术大全
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • #if等命令的学习
  • #include<初见C语言之指针(5)>
  • #QT(串口助手-界面)
  • #stm32驱动外设模块总结w5500模块
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (Git) gitignore基础使用
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (ZT)出版业改革:该死的死,该生的生
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (四)汇编语言——简单程序
  • (四)事件系统
  • (算法)区间调度问题
  • (一)Neo4j下载安装以及初次使用
  • (一)插入排序
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转载)hibernate缓存
  • (自用)网络编程
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .net Signalr 使用笔记
  • .NetCore部署微服务(二)