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

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

相关推荐
学长毕设34 分钟前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
码途行者1 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
SimonKing1 小时前
震惊:怎么回事,opencode一轮对话耗尽免费额度
java·后端·程序员
装不满的克莱因瓶1 小时前
【SpringAI Alibaba】ReactAgent响应SSE实时流式传输案例实战
java·人工智能·ai·sse·springai
杨凯凡1 小时前
Spring Boot 文件上传怎么做才安全?流式落盘、路径校验与数据库一致性实战
java·spring boot·文件上传·后端安全·数据库一致性
旖旎夜光1 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
这个昵称不容易2 小时前
旅游管理系统的设计与实现(SpringBoot + MySQL + Vue 前后端分离)
java·springboot·毕设
Rain的Java大神之路2 小时前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
你看我名字2 小时前
产品参数昨天还对,今天已过期:数眼智能与大模型应用如何做资料版本校验
开发语言·架构
老秦包你会2 小时前
计算机网络第二课 ----Socket(套接字)编程预备
开发语言·计算机网络·php