CONFIDENTIAL
jvm
JVM(Java 虚拟机)是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。它屏蔽了底层操作系统(Windows, Linux, macOS)的差异,使得 Java 程序只需编译一次,即可在任何安装了 JVM 的平台上运行(linux,win,mac的jvm都能运行同一份字节码),即 “Write Once, Run Anywhere”。

jvm结构


绿色区域
- 程序计数器:存储当前正在执行的java方法jvm指令地址。每个线程有一个独立的程序计数器,用于管理线程的执行状态。该部分是唯一一个在Java虚拟机规范中没有规定大小的区域。(记录程序的某个线程运行到哪了)
- Java虚拟机栈:每个线程在JVM中会创建一个虚拟机栈,用于存储方法调用时的局部变量(基本数据类型放栈里,如果是对象只存对象的引用,实际空间分配在java堆里)、操作数栈、动态链接等数据。虚拟机栈的大小和调用方法的深度密切相关,如果栈空间不足,通常会抛出
StackOverflowError或OutOfMemoryError。 - 本地方法栈:与Java虚拟机栈类似,主要用于执行本地方法(Native方法,也就是c,c++写的能调用系统底层的方法)。本地方法栈通常会涉及调用系统原生的功能,可能会抛出
StackOverflowError或OutOfMemoryError。
蓝色区域
- Java堆:JVM中最大的一块内存区域,主要用于存放对象实例。Java堆被划分为多个区域,如Eden区和两个Survivor区(From Survivor和To Survivor),用于存储新生代和老年代的对象。如果堆空间不足,JVM会抛出
OutOfMemoryError。详情看 [[gc#三、jvm堆结构与分代回收机制(Generational GC)]] - 方法区(元空间):方法区存放类的元数据、静态变量、常量池等信息。在JDK 1.8及以后,方法区被替换为元空间,存放的是类的元数据(入类的全名、方法的签名、类的字段),而不是直接存在堆内存中。元空间的内存大小可以根据需要动态扩展,可能会导致
OutOfMemoryError异常。元空间放在主内存(操作系统内存中)- 类的元数据:存放的是类的元数据(如类的全名、方法的签名、类的字段),
- 常量池:常量池是存放类中的常量值,如字符串常量、数字常量等。在JDK 1.8之前,常量池是存放在永久代中的,从JDK 1.8开始,它也存放在元空间中。如
public static final String CONSTANT = "hello";,这里的”hello”就是常量池中的一个值。 - 方法和字段信息:元空间存储的是类中方法和字段的描述信息,包括方法名、参数类型、返回值类型等。具体的字节码内容并不存放在元空间中,字节码存放在方法区的另一部分。 例如:对于一个
public void foo()方法,元空间会存储方法的签名和访问权限,但实际字节码存储在其他地方。 - 运行时常量池:是方法区的一部分,主要用于存储类和方法中的常量数据。常量池在JVM运行时从类文件中加载并保存常量,可能会发生
OutOfMemoryError。
其他区域
- 类装载(类加载)系统 [[java类加载]]
- 垃圾回收器 [[gc#三、jvm堆结构与分代回收机制(Generational GC)]]
- 执行引擎:将java字节码解释为底层系统的一个指令