JVM 运行时内存模型

JVM 运行时内存共分为虚拟机栈、堆、元空间、程序计数器、本地方法栈五个部分

java 复制代码
import com.test.domain.User;
public class Main{
	static int count = 0;
	public static void main(String[] args){
		run();
	}
	public static void run(){
		String name = "zhangsan";
		User user = new User();
	}
	
	public native void test();
}

JVM 的内存结构主要分为以下几个部分:

虚拟机栈

用来存储每个线程的执行信息,即每个线程都有自己独立的虚拟机栈。每个方法在执行时都会在虚拟机栈中创建一个对应的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

比如上面的代码,在运行 main() 方法的时候,会先把 main() 方法压入 JVM 虚拟机栈;当 main 调用 run() 方法时,又会新建一个栈帧并将 run() 压入栈中。该栈帧的局部变量表中会存储 name 和 user 这两个局部变量。


堆

是 JVM 中最大的一块内存区域,被所有线程共享,在虚拟机启动时创建,用于存放对象实例。

仍以上面代码为例:new User() 会在堆内存中创建一个 User 对象,并返回其地址;run() 方法栈帧中的局部变量 user 则保存该对象的引用(即地址)。
从 JDK 7 开始,字符串常量池(String Table)被从方法区移入了堆内存 。因此,字面量 "zhangsan" 会被存放在堆中的字符串常量池里。
原因包括:

  • 方法区(永久代)空间有限,大量字符串容易导致 OutOfMemoryError: PermGen space;
  • 字符串对象本身就在堆中,将常量池也放在堆中更便于垃圾回收。

元空间(方法区)

在 JDK 8 之前称为"方法区",JDK 8 及以后由"元空间"实现,使用本地内存(而非 JVM 堆内存),用于存储已被虚拟机加载的类元数据,包括:类结构信息、字段和方法的描述信息(如名称、类型、访问标志)、方法字节码、运行时常量池(非字符串对象)等。

仍以上述代码为例:public class Main 的类信息、static int count = 0; 的字段描述 (如字段名 "count"、类型 int、修饰符 static)等都会被加载到元空间中。
注意 :静态变量的值 (如 count = 0)并不直接存在元空间,而是作为 Main.class 对象的一部分,存储在 Java 堆 中。

🔍 拆解说明:static int count = 0; 到底存哪?
内容 存储位置 说明
字段名 "count"、类型 int、访问标志 static ✅ 元空间 属于类的元数据,用于反射、JIT 编译等
静态变量的值 0 ✅ Java 堆 作为 Main.class(Class 对象)的一个字段值存储
Main.class 这个对象本身 ✅ Java 堆 在 JDK 8+ 中,所有 Class 对象都在堆中

因此,当你访问 Main.count 时,JVM 实际是从堆中的 Main.class 对象里读取这个值。


程序计数器

用于记录当前线程正在执行的 Java 方法的 JVM 字节码指令地址。每个线程都有独立的程序计数器。当线程切换时,程序计数器能确保线程恢复执行时从正确的位置继续。

如果当前执行的是 Native 方法,程序计数器的值为 undefined。


本地方法栈

与 Java 虚拟机栈作用类似,但专为虚拟机调用 Native 方法(如 C/C++ 编写的代码)服务。在 HotSpot 虚拟机中,本地方法栈和 Java 虚拟机栈实际是合二为一 的。本地方法执行时也会创建栈帧,同样可能出现 StackOverflowError 或 OutOfMemoryError。

上面代码中的 public native void test(); 方法,其调用过程由本地方法栈支持。


✅ 总结 :

JVM 运行时内存主要分为五部分:虚拟机栈、堆、元空间(方法区)、程序计数器、本地方法栈。其中堆和元空间是线程共享的,其余均为线程私有。


作者:不会写程序的未来程序员

首发于 CSDN

版权声明:本文为原创文章,转载请注明出处。

相关推荐
Pniubi2 小时前
HashMap的扩容和树化边界
java·开发语言
Mikko73 小时前
用 Java 复刻了高中时在塞班上玩的「熔岩矿车」:纯 Swing、零依赖、没有一张图片,一个 jar 双击就能玩
java·游戏开发·swing
知了学历孙老师3 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
Java爱好狂.3 小时前
Java初学者如何一周速通SpringBoot!
java·spring boot·后端·spring·高并发·架构师·java面试
秋饼4 小时前
LLM API密钥动态轮换实战:Spring Vault + Spring AI + 多Provider路由
java·ai·技术分享·后端开发
gCode Teacher 格码致知4 小时前
Pandas教学-17:Series与Dataframe的关系
开发语言·python·pandas
发量惊人的中年网工4 小时前
分公司访问总部ERP慢怎么办?SD-WAN组网的排查与验收要点
服务器·开发语言·php
下页、再停留5 小时前
【C#桌面客户端系列学习-15】生成可视化图表之折线图、柱状图、饼状图
开发语言·c#
ShineWinsu5 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说5 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json