为了描述JVM运行时内存空间,Java的开发者在《Java虚拟机规范》中指出:JVM (运行时数据区)内存共分为:
- JVM栈
- 堆
- 方法区
- 程序计数器
- 本地方法栈
这五大区域,示意图如下:
详细解释各个区域的用途:
1. JVM栈
描述的是Java的普通方法执行时的所占内存空间的内存模型。局部变量会直接存储在栈中。
栈:是一种数据结构,特点是“先进后出”(先进的处于栈底,后进的处于栈顶)
普通方法:所有Java代码书写实现的方法以及JVM内部创建的一些方法。总之是和Java语言本身相关的一些方法。
于是方法的执行流程在JVM内存中,就变成如下这样:
- 每当Java程序执行一个方法,都会在栈上分配一块只属于该方法的内存区域,称之为栈帧。都会将一个存储该方法信息的栈帧压入栈中,称之为方法进栈(或方法调用)。
- 方法进栈的同时局部变量开辟内存空间存储值,局部变量生效。
- 当方法执行完毕后,该方法的栈帧随之销毁,称之为方法出栈。
- 方法栈桢被销毁的同时,局部变量也被销毁,局部变量失效。
- 方法调用依赖于栈的先进后出完成,栈中只有处于栈顶的栈帧才会生效,表示正在执行的方法,称之为当前栈帧、当前方法。
于是可以理解局部变量的生命周期:
方法中的局部变量都有自己的方法栈桢,不同方法的方法栈桢之间不会相互影响,故局部变量仅在方法或在作用域内生效。因此,方法中的局部变量随着方法的调用生效,随着方法的执行结果,销毁失效,即局部变量与方法调用“同生共死”。
2. 本地方法栈(native method stack)
和JVM栈一样,是描述方法调用的内存模型,区别在于本地方法栈是描述本地方法调用的内存模型。
本地方法:指的是Java代码中使用native关键字修饰的方法,本地方法都不是由Java代码实现的方法,一般来说是由C/C++语言实现的方法。
3. 堆(heap)
堆是JVM内存中最大的一块,new创建的对象(object)都存储在堆上。
new关键字:在堆上开辟一片空间给相应的对象,JVM创建对象,在堆上存储。new关键字一定会在堆上创建一个独立的,新的对象。
4. 方法区(method area)
(见面向对象)
5. 程序计数器
JVM执行代码是解释执行的,即一行一行执行字节码的,程序计数器用来记录当前执行的行数。