返回

深入浅出Java语言的JVM内存结构

后端

一、JVM内存结构概述

在Java的世界中,一切都是对象。无论是基本类型还是复杂类型,都被看作是对象。在Java应用程序运行期间,JVM会为每个对象分配内存空间,这些内存空间可以分为以下5个部分:

  • 堆(Heap) :堆是Java应用程序中最大的内存区域,用于存储所有对象实例以及数组。堆的大小可以通过-Xmx-Xms参数进行设置,默认情况下,堆的大小是物理内存的1/4。
  • 栈(Stack) :栈是Java应用程序中用于存储局部变量和操作数的内存区域。栈的大小可以通过-Xss参数进行设置,默认情况下,栈的大小是1MB。
  • 方法区(Method Area) :方法区是Java应用程序中用于存储已被加载的类信息、常量和静态变量的内存区域。方法区的大小可以通过-XX:MaxPermSize参数进行设置,默认情况下,方法区的大小是物理内存的1/4。
  • 本地方法栈(Native Method Stack) :本地方法栈是Java应用程序中用于存储本地方法的内存区域。本地方法栈的大小可以通过-Xss参数进行设置,默认情况下,本地方法栈的大小是1MB。
  • 程序计数器(Program Counter Register) :程序计数器是Java应用程序中用于存储当前正在执行的指令地址的内存区域。程序计数器的大小通常是4字节,但是具体大小取决于JVM的实现。

二、堆(Heap)

堆是Java应用程序中最大的内存区域,用于存储所有对象实例以及数组。堆的大小可以通过-Xmx-Xms参数进行设置,默认情况下,堆的大小是物理内存的1/4。

堆内存被分为年轻代和老年代,年轻代又分为Eden空间、Survivor空间0和Survivor空间1。对象在被创建后首先被分配到Eden空间,当Eden空间满时,会触发一次Minor GC,将Eden空间和Survivor空间0中存活的对象复制到Survivor空间1中,然后清空Eden空间和Survivor空间0。当Survivor空间1满时,会触发一次Major GC,将Survivor空间1中存活的对象复制到老年代中,然后清空Survivor空间1。

三、栈(Stack)

栈是Java应用程序中用于存储局部变量和操作数的内存区域。栈的大小可以通过-Xss参数进行设置,默认情况下,栈的大小是1MB。

栈内存是线程私有的,每个线程都有自己的栈内存。栈内存是先入后出的,即后进先出(LIFO)的。当一个方法被调用时,会创建一个新的栈帧,用于存储该方法的局部变量和操作数。当方法执行完毕后,栈帧会被销毁。

四、方法区(Method Area)

方法区是Java应用程序中用于存储已被加载的类信息、常量和静态变量的内存区域。方法区的大小可以通过-XX:MaxPermSize参数进行设置,默认情况下,方法区的大小是物理内存的1/4。

方法区是共享的,所有线程都共享同一个方法区。方法区在JVM启动时被创建,并在JVM关闭时被销毁。

五、本地方法栈(Native Method Stack)

本地方法栈是Java应用程序中用于存储本地方法的内存区域。本地方法栈的大小可以通过-Xss参数进行设置,默认情况下,本地方法栈的大小是1MB。

本地方法栈是线程私有的,每个线程都有自己的本地方法栈。本地方法栈是先入后出的,即后进先出(LIFO)的。当一个本地方法被调用时,会创建一个新的本地方法栈帧,用于存储该本地方法的局部变量和操作数。当本地方法执行完毕后,本地方法栈帧会被销毁。

六、程序计数器(Program Counter Register)

程序计数器是Java应用程序中用于存储当前正在执行的指令地址的内存区域。程序计数器的大小通常是4字节,但是具体大小取决于JVM的实现。

程序计数器是线程私有的,每个线程都有自己的程序计数器。程序计数器在JVM启动时被创建,并在JVM关闭时被销毁。

七、总结

Java虚拟机(JVM)的内存结构包括堆、栈、方法区、本地方法栈和程序计数器5个部分。其中,堆是用于存储所有对象实例以及数组的内存区域;栈是用于存储局部变量和操作数的内存区域;方法区是用于存储已被加载的类信息、常量和静态变量的内存区域;本地方法栈是用于存储本地方法的内存区域;程序计数器是用于存储当前正在执行的指令地址的内存区域。