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

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

相关推荐
hello 早上好1 天前
04_JVM 类加载子系统与内存结构
jvm
菜鸟233号1 天前
力扣647 回文子串 java实现
java·数据结构·leetcode·动态规划
qq_12498707531 天前
基于Java Web的城市花园小区维修管理系统的设计与实现(源码+论文+部署+安装)
java·开发语言·前端·spring boot·spring·毕业设计·计算机毕业设计
h7ml1 天前
查券返利机器人的OCR识别集成:Java Tesseract+OpenCV优化图片验证码的自动解析方案
java·机器人·ocr
野犬寒鸦1 天前
从零起步学习并发编程 || 第五章:悲观锁与乐观锁的思想与实现及实战应用与问题
java·服务器·数据库·学习·语言模型
Volunteer Technology1 天前
Sentinel的限流算法
java·python·算法
岁岁种桃花儿1 天前
SpringCloud从入门到上天:Nacos做微服务注册中心
java·spring cloud·微服务
jdyzzy1 天前
什么是 JIT 精益生产模式?它与传统的生产管控方式有何不同?
java·大数据·人工智能·jit
Chasmれ1 天前
Spring Boot 1.x(基于Spring 4)中使用Java 8实现Token
java·spring boot·spring
froginwe111 天前
Python 条件语句
开发语言