带你分清JVM中各分区扮演的角色,彻底掌握JAVA内存管理
2023-11-28 10:29:44
JVM内存分区概述
JVM将内存划分为若干个不同的数据区域,每个区域都有各自的用户级创建销毁时间,这些区域包括:
- 堆:是Java虚拟机所管理的内存中最大的一块,所有对象的实例都被分配在堆中。堆是所有线程共享的,可以通过
-Xmx
和-Xms
参数来指定堆的最大值和最小值。 - 堆栈:是每个线程私有的,每个线程都有自己的堆栈。堆栈中存储着局部变量、方法调用信息等数据。堆栈的大小可以通过
-Xss
参数来指定。 - 方法区:是所有线程共享的,存储着类的信息、常量、静态变量等数据。方法区的大小可以通过
-XX:PermSize
和-XX:MaxPermSize
参数来指定。 - 本地方法栈:是用来执行本地方法的,本地方法栈的大小可以通过
-XX:NativeStackSize
参数来指定。 - 程序计数器:用来存储当前线程正在执行的指令的地址,程序计数器的大小通常很小。
堆
堆是JVM所管理的内存中最大的一块,所有对象的实例都被分配在堆中。堆是所有线程共享的,可以通过-Xmx
和-Xms
参数来指定堆的最大值和最小值。
堆分为新生代和老年代,新生代又细分为伊甸园区、幸存者区0和幸存者区1。新生代的大小可以通过-Xmn
参数来指定,老年代的大小可以通过-Xms
参数来指定。
新生代中,伊甸园区是用来存放新创建的对象,当伊甸园区满了的时候,就会触发一次新生代垃圾回收,将伊甸园区中已经死亡的对象回收掉,并将幸存的对象复制到幸存者区0中。当幸存者区0满了的时候,就会触发一次幸存者区垃圾回收,将幸存者区0中已经死亡的对象回收掉,并将幸存的对象复制到幸存者区1中。当幸存者区1满了的时候,就会触发一次幸存者区垃圾回收,将幸存者区1中已经死亡的对象回收掉,并将幸存的对象复制到老年代中。
老年代中,当老年代满了的时候,就会触发一次老年代垃圾回收,将老年代中已经死亡的对象回收掉。
堆栈
堆栈是每个线程私有的,每个线程都有自己的堆栈。堆栈中存储着局部变量、方法调用信息等数据。堆栈的大小可以通过-Xss
参数来指定。
堆栈是一个后进先出的数据结构,当方法被调用的时候,会在堆栈中创建一个新的栈帧,当方法返回的时候,会销毁该栈帧。
方法区
方法区是所有线程共享的,存储着类的信息、常量、静态变量等数据。方法区的大小可以通过-XX:PermSize
和-XX:MaxPermSize
参数来指定。
方法区在Java 8之前称为永久代,在Java 8之后永久代被移除了,方法区的大小不再受到限制。
本地方法栈
本地方法栈是用来执行本地方法的,本地方法栈的大小可以通过-XX:NativeStackSize
参数来指定。
本地方法栈是一个后进先出的数据结构,当本地方法被调用的时候,会在本地方法栈中创建一个新的栈帧,当本地方法返回的时候,会销毁该栈帧。
程序计数器
程序计数器用来存储当前线程正在执行的指令的地址,程序计数器的大小通常很小。
程序计数器是一个寄存器,当一条指令被执行的时候,程序计数器会指向下一条要执行的指令的地址。