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() 压入栈中。该栈帧的局部变量表中会存储 nameuser 这两个局部变量。


是 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 虚拟机栈实际是合二为一 的。本地方法执行时也会创建栈帧,同样可能出现 StackOverflowErrorOutOfMemoryError

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


总结

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


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

首发于 CSDN

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

相关推荐
躺平大鹅4 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者5 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺5 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart6 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP7 小时前
MyBatis-mybatis入门与增删改查
java
孟陬10 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌10 小时前
一站式了解四种限流算法
java·后端·go
华仔啊11 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java
也些宝12 小时前
Java单例模式:饿汉、懒汉、DCL三种实现及最佳实践
java