JVM,即Java虚拟机,其是Java程序的运行环境,是Java技术的核心组成部分,本次就JVM的自动内存管理详细展开:
JVM的内存区域分为2大类,即线程私有的和线程共享的,前者分为3大块,虚拟机栈、本地方法栈、程序计数器。后者分为2大块,堆与方法区。
首先是私有的3大块区域:
1、程序计数器:程序计数器是一个较小的内存区域,其用于记录当前线程所执行的字节码指令的地址。每一个线程都有一个自己的程序计数器,其可以使线程切换时,快速的恢复到正确的执行位置。程序计数器的划分和管理是实现JVM高效运行和内存管理的基础。
2、虚拟机栈:其生命周期与线程一样,在创建线程时,会自动创建一个虚拟机栈,在每个方法在执行时,都会创建一个栈帧,其用于存储局部变量表、操作数栈、动态链接和方法出口等信息。每一个方法调用时,这个栈帧就会入栈,方法结束时,则会出栈。即每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
不过,值得注意的是,在虚拟机栈中局部变量表部分中, 放了编译期可知的各种Java虚拟机基本数据类型(boolean、bytechar、short、int、 float、long、double)、对象引用(reference),它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。。这些数据类型在局部变量表中的存储空间以局部变量槽(Slot)来表示,其中64位长度的long和double类型的数据会占用两个变量槽,其余的数据类型只占用一个。
3、本地方法栈:其与虚拟机栈功能接近,只不过其是为虚拟机使用到的本地方法服务。
然后是线程共享的2个区域:
1、堆:堆是JVM管理的内存中最大的一块,其主要作用是存放对象实例和数组。堆也是垃圾收集器管理的内存区域,所以通常会被进一步划分为新生代、老年代、永久代等。不过无论从什么角度,无论如何划分,都不会改变堆中存储内容的共性,无论是哪个区域,存储的都只能是对象的实例,将堆细分的目的只是为了更好地回收内存,或者更快地分配内存。
2、方法区:其用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。