JVM内存分配

内存布局

JVM内存大概分为几块区域:堆、栈、程序计数器、MetaSpace元空间、直接内存区,见下图

线程级内存区域:栈、程序计数器,堆与操作系统一样多个线程共享。

本地方法栈

本地方法栈是和虚拟机栈非常相似的一个区域,它服务的对象是 native 方法。你甚至可以认为虚拟机栈和本地方法栈是同一个区域

Java虚拟机栈

Java虚拟机栈中存放的是栈帧(Frame),而运行的每个方法都会产生一个栈帧,最后执行的方法栈帧在栈顶,所以是FILO。一个栈帧中包含:

  1. 局部变量表: 存放局部变量的引用
  2. 动态链接:
  3. 操作数栈:执行字节码的地方,类比操作系统的栈执行过程。
  4. 返回地址:只存在于字节码层面,对于 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区
posted @   林一gg  阅读(100)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示