返回

带你分清JVM中各分区扮演的角色,彻底掌握JAVA内存管理

Android

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参数来指定。

本地方法栈是一个后进先出的数据结构,当本地方法被调用的时候,会在本地方法栈中创建一个新的栈帧,当本地方法返回的时候,会销毁该栈帧。

程序计数器

程序计数器用来存储当前线程正在执行的指令的地址,程序计数器的大小通常很小。

程序计数器是一个寄存器,当一条指令被执行的时候,程序计数器会指向下一条要执行的指令的地址。