JVM内存模型(万字图文全面详解)

JVM内存模型(万字图文全面详解)-mikechen

JVM内存模型在Java面试经常被问到,比如:JVM内存模型的组成及实现等,下面我就重点来详解JVM内存模型@mikechen

JVM内存模型

JVM内存模型的整体结构,如下图所示:

JVM内存模型(万字图文全面详解)-mikechen

包含:JVM堆虚拟机栈程序计数器Java方法区本地方法栈,下面我会一一来详解JVM内存模型的5大区域@mikechen

 

堆(Heap)

JVM堆是Java虚拟机管理的内存中最大的一块,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。

如下图所示:

JVM内存模型(万字图文全面详解)-mikechen

1.新生代(Young Generation)

新生代是JVM堆的一部分,用于存储新创建的对象,新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

当一个对象被创建时,它会被分配到Eden区,当Eden区满时,JVM会启动垃圾回收,清理无用的对象,并将剩余的对象移动到Survivor区。

2.老年代(Old Generation)

老年代是JVM堆的另一部分,用于存储已经存活了一段时间的对象,老年代的空间通常比新生代大,并且包含更多的对象。

3.永久代(PermGen)

永久代是JVM堆的另一个组成部分,用于存储类的元数据和静态数据。

4.元空间(Metaspace)

在JDK 8之后,永久代已经被Metaspace取代,Metaspace是一块与堆独立的内存空间,用于存储类的元数据和静态数据。

 

方法区(Method Area)

Java方法区,英文全称是Method Area,是JVM内存中的一个重要区域,与堆一样是各个线程所共享的内存区域。

其实方法区是在JDK1.8以前的版本里存在的一块内存区域,主要就是存放从class文件里加载进来的类的,而且常量池也是在这块区域内的。

但是在JDK1.8之后,这块区域摇身一变,换了名字,叫做“Metaspace”,翻译过来就是“元数据空间”的意思,当然它只是改了个名,实现的功能是没变的。

JVM内存模型(万字图文全面详解)-mikechen

1.类型信息

类数据主要包括:类名、访问修饰符、父类名、接口列表、字段数据、方法数据和注解信息等。

 

2.域信息(Field)成员变量

域的相关信息包括:域名称、域类型、域修饰符。

比如:public, private,protected,static,final, volatile, transient等等。

 

3.方法数据

方法数据主要:存储类或接口中声明的方法信息,方法包括静态方法和实例方法。

比如:

  • 方法的返回类型:方法参数的数量和类型、或void;
  • 方法的修饰符:public, private,protected,static, final,synchronized,abstract等;

 

4.运行时常量池(Runtime Constant Pool)

运行时常量池存放类中的常量,包括:字符串、final修饰的常量等。

 

虚拟机栈(JVM Stack)

虚拟机栈,英文全称Java Virtual Machine Stack,主要作用就是:主管Java程序的运行,它保存方法的局部变量、部分结果,并参与方法的调用和返回。

每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用,如下图所示:

JVM内存模型(万字图文全面详解)-mikechen

栈帧包含了:局部变量表、操作数栈、动态链接、方法返回地址等信息。

1.局部变量表(Local Variable Table)

局部变量表是虚拟机栈中的一部分,用于存储方法执行过程中的局部变量。

 

2.操作数栈(Operand Stack)

操作数栈用于存储方法执行时的操作数,当一个方法被调用时,它的参数被压入操作数栈中,方法内部的操作数也会被压入操作数栈中。

 

3.动态链接(Dynamic Linking)

动态链接是指在方法调用时,将方法所在的类和方法的字节码在运行时动态链接起来的过程。

动态链接的目的是为了让虚拟机能够找到方法的实现,以便进行调用。

 

4.方法返回地址(Return Address)

方法返回地址是指在方法调用时,JVM会将调用者的返回地址存储在虚拟机栈中。

当方法执行完毕后,JVM会从虚拟机栈中读取返回地址,并跳转到该地址继续执行调用者的代码。

 

本地方法栈(Native Stack)

本地方法栈,英文全称是Native Method Stack,是JVM内存结构的组成部分,如下图所示:

JVM内存模型(万字图文全面详解)-mikechen

本地方法栈用于执行本地方法,本地方法是用其他语言,比如:C/C++编写的方法,在Java程序中通过JNI(Java Native Interface)来调用。

 

程序计数器(PC Register)

程序计数器,英文名Program Counter,是一种专门用来存储当前正在执行的指令地址的寄存器,它保证了指令的顺序执行和分支指令的正确执行。

Java编程里的:分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

1.记录下一条指令的地址

程序计数器存储的是当前正在执行的指令的地址,当处理器执行完当前指令后,会根据程序计数器中的地址获取下一条要执行的指令的地址。

2.协调指令的执行

程序计数器的值会随着指令的执行而不断变化,确保处理器按照指令的顺序依次执行每条指令。

3.支持分支指令的执行

当处理器执行分支指令(如条件分支、循环等)时,程序计数器会根据指令的执行结果更新指令地址,以确保处理器执行正确的指令。

4.提供异常处理支持

当处理器发生异常,比如:中断、故障等时,程序计数器会存储异常处理程序的地址,使得处理器能够跳转到异常处理程序开始执行。

以上就是JVM内存模型的详解,更多JVM内容,请查看:JVM(Java虚拟机)从0到1全部合集

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法