JVM执行Java程序时内存的划分
Java虚拟机在执行Java程序过程中会把它所管理的内存区域划分为若干个不同的数据区域。
Java虚拟机所管理的内存包括以下几个运行时区域:
1、程序计数器(Program Couter Register)
程序计数器是一块较小的内存空间,作用是当前线程所执行的字节码的行号指示器。字节码指示器就是通过改变程序计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依靠程序计数器来完成。
2、Java虚拟机栈(Java Virtual Machine Stacks)
VM Stack 生命周期和线程相同。
每个方法没执行的同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法被调用直至完成的过程对应着一个栈帧在VM Stack的入栈和出栈的过程。
VM Stacks也可以说是局部变量表。局部变量表存放了预编译期可知的各种数据类型(boolean、byte、char、short、int、float、long、double)、对象引用和returnAddress(指向了一个字节码指令的地址)。
3、本地方法栈(Native Method Stack)
本地方法栈(Native Method Stack)与虚拟机栈(VM Stack)所发挥的作用非常相似。不同在于:
虚拟机栈(VM Stack)为虚拟机执行Java方法(也就是字节码)服务;
本地方法栈(Native Method Stack)为虚拟机用到的Native方法服务。
注:Native Method就是java调用非java代码的接口,该方法的实现由非java代码实现,比如C、C++
4、Java堆
Java堆是被所有线程共享的一块区域,在虚拟机启动时创建。此内存区域唯一的目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存的。
Java堆是垃圾回收器管理的主要区域,因此很多时候被称作“GC堆”。
Java堆可以处于物理上不连续的内存空间。在实现时既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果堆中没有完成实例分配,并且堆也没办法再扩展的时候就会抛出OutOfMemoryError异常。
5、方法区(Method Area)
方法区(Method Area)和Java堆一样,是各个线程共享的一块区域,用于存储已被虚拟机加载的的类信息、常量、静态变量、即时编译器编译后的代码等数据。
方法区和Java堆一样在内存区上不需要连续的内存,可以选择固定大小或者可扩展外,还可以选择不实现垃圾回收。相对而言垃圾回收在这个区域比较少见。这个区域内存回收的目标是针对常量池的回收和对类型的卸载。
运行时常量池(Runtime Constant Pool):是方法区的一部分。calss文件中除了类的版本信息、字段、方法、接口等描述信息外,还有一项信息就是常量池(用于存放编译器生成的各种字面量和符号引用),这部分内容将在类加载后存放在方法区的运行时常量区。
注:运行期间可以将新的常量放入池中,这种特性被开发人员用的多的是String类的intern()方法。