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

内存区划分

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

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

一般我们面试的时候,都是笼统的说:堆、栈、以及方法区,JDK 8之后方法区变为"元空间"。

这个说法不错,下面我们详解一下。

程序计数器

程序计数器区域⼀块内存较小的区域,它⽤于存储线程的每个执行指令,每个线程都有自己的程序计数器,此区域不会有内存溢出的情况。

由于Java虚拟机的多线程是通过线程的轮流切换、分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都只执行一个线程。

那么为了每次切换线程后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器, 所以这个程序计数器区域,是一个线程私有的内存。

虚拟机栈与本地线程栈

在很多情况下,我们都是把这两个合在一起说的。

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

如果按照我这里的浅显理解的话,他们之间的区别可以这么说。

虚拟机栈的生命周期与线程相同,主要就是存储线程执行相关的局部变量信息。

本地方法栈也是如此,但是所执行的内容可能是虚拟机本地方法Native。

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

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

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

还有一个情况是,栈帧层层递进的时候,虚拟机栈也是在不断增大。

如果栈的内存不足,并且提前分配好不能扩展;或者是扩展的时候无法申请到足够的内存,就会发生OutOfMemoryError异常。

堆区

堆区是各个线程共享的区域。

这也是老生常谈的问题,主要存放JVM启动时创建的数组和对象实例,还有垃圾回收也主要在堆区发生,还有分代模型等等巴拉巴拉。

具体内容我们可以到分析垃圾回收的时候详细说下。

需要注意的是,堆区也是可以被固定大小的,当内存不足无法扩展时,也会抛出OutOfMemoryError异常。

方法区

与堆区一样,也是各个线程共享的区域。

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

这里不得不提一下"永久代" 这个概念,以前很多时候都是把永久代与方法区混为一谈。

这是因为HotSpot虚拟机的设计团队把垃圾收集器的分代设计扩展到了方法区,把方法区称为永久代来管理垃圾回收机制。

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

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

运行时常量池

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

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

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

相关推荐
艾伦~耶格尔39 分钟前
【集合框架LinkedList底层添加元素机制】
java·开发语言·学习·面试
一只叫煤球的猫1 小时前
🕰 一个案例带你彻底搞懂延迟双删
java·后端·面试
IT利刃出鞘5 小时前
Java线程的6种状态和JVM状态打印
java·开发语言·jvm
慧翔天地人才发展学苑5 小时前
大厂 | 华为半导体业务部2026届秋招启动
华为·面试·职场和发展·跳槽·求职招聘·职场晋升
liang_jy5 小时前
数组(Array)
数据结构·面试·trae
天天摸鱼的java工程师6 小时前
Java 解析 JSON 文件:八年老开发的实战总结(从业务到代码)
java·后端·面试
小高0076 小时前
📈前端图片压缩实战:体积直降 80%,LCP 提升 2 倍
前端·javascript·面试
普罗米拉稀6 小时前
Flutter 复用艺术:Mixin 与 Abstract 的架构哲学与线性化解密
flutter·ios·面试
程序员三藏7 小时前
Selenium+python自动化测试:解决无法启动IE浏览器及报错问题
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
黑客影儿7 小时前
Java技术总监的成长之路(技术干货分享)
java·jvm·后端·程序人生·spring·tomcat·maven