JVM内存分配
内存布局
JVM内存大概分为几块区域:堆、栈、程序计数器、MetaSpace元空间、直接内存区,见下图
线程级内存区域:栈、程序计数器,堆与操作系统一样多个线程共享。
本地方法栈
本地方法栈是和虚拟机栈非常相似的一个区域,它服务的对象是 native 方法。你甚至可以认为虚拟机栈和本地方法栈是同一个区域
Java虚拟机栈
Java虚拟机栈中存放的是栈帧(Frame),而运行的每个方法都会产生一个栈帧,最后执行的方法栈帧在栈顶,所以是FILO。一个栈帧中包含:
- 局部变量表: 存放局部变量的引用
- 动态链接:
- 操作数栈:执行字节码的地方,类比操作系统的栈执行过程。
- 返回地址:只存在于字节码层面,对于 JVM 来说,程序就是存储在方法区的字节码指令,而 returnAddress 类型的值就是指向特定指令内存地址的指针
程序计数器
线程级别内存,程序计数器存储了当前正在运行的流程,包括正在执行的指令、跳转、分支、循环、异常处理等,简单理解为记录当前线程执行字节码的行号的区域。
堆
堆是 JVM 上最大的内存区域 ,多线程共享区域,我们经常说一个变量是非线程安全的,那这个变量一定就存放在堆里面, 堆也是GC的重点对象。
一个对象创建的时候,到底是在堆上分配,还是在栈上分配呢?这和两个方面有关:对象的类型和在 Java 类中存在的位置。Java 的对象可以分为基本数据类型和普通对象
- 对于普通对象来说,JVM 会首先在堆上创建对象,然后在其他地方使用的其实是它的引用。比如,把这个引用保存在虚拟机栈的局部变量表中。
- 对于基本数据类型来说(byte、short、int、long、float、double、char),有两种情况。
当在方法体内声明了基本数据类型的对象,它就会在栈上直接分配。其他情况,都是在堆上分配。
像 int[] 数组这样的内容,是在堆上分配的。数组并不是基本数据类型
元空间
存放类的信息、常量池、方法数据、方法代码等,元空间属于堆外内存,-XX:MaxMetaspaceSize 来控制大小。这里解释下:方法区是JVM规范中的一个逻辑概念,在Java8之前叫永久代(Perm Area) , 可以理解为 Java8 之前方法区的实现是永久代,Java8 之后是元空间。
常量池
- 字符串常量池:java8在堆中,java8之前是perm区。虽然java8之前perm也属于堆区,但是此堆非彼堆。
- 类文件常量池:metaspace区
- 运行时常量池:metaspace区
本文来自博客园,作者:林一gg,转载请注明原文链接:https://www.cnblogs.com/linyigg/p/13291220.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端