Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。
下面介绍下内存中各个数据区:
PC寄存器/程序计数器(线程私有):
程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器
JAVA虚拟机栈(线程私有):
生命周期与线程相同,即创建线程的同时创建的,用于存放栈帧。栈帧是一个方法在执行的时候存储局部变量表、操作数栈、操作数栈,动态链接、方法出口灯信息。每个方法调用完后会将应的栈帧从JAVA虚拟机栈中出栈。如果线程请求的栈深度大于虚拟机的栈深度,会抛出SatckOverflowError异常
本地方法栈(线程私有):
本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。
JAVA堆(线程共享):
所有的对象实例以及数组都要在堆上分配,是垃圾收集器管理的主要区域。这块是我们主要关注的模块,之后一些GC算法和GC处理器都是针对这块的
方法区(线程共享):
它用于存储已被虚拟机加载的类信息、 常量、 静态变量、 即时编译器编译后的代码等数据。其中运行时常量池是方法区的一部分。
上面JAVA堆和方法区是线程共享的,其实只要理解JAVA堆和方法区存放什么就很好理解了为什么这两个是共享的部分。对于线程独有的这部分内存,都是随着线程的启动而创建,而当线程被销毁时,内存也就随之释放。这一部分内存,不需要垃圾搜集器的管理,而是JAVA虚拟机来主动管理,每当一个线程被创建的时候,JAVA虚拟机就会为其分配相应的PC寄存器和JAVA虚拟机栈,如果需要的话,还会有本地方法栈。相应的,当一个线程被销毁的时候,JAVA虚拟机也会将这个线程所占有的内存全部释放。相对于线程独有的那部分内存,全局共享的这部分内存更加难以处理,不过这只是针对于虚拟机的实现来说,因为这一部分内存是要实现自动内存管理系统(GC)的。全局共享的这部分内存(以下简称堆),内存分配主要是由程序员显示的使用new关键字来触发的,至于new出来的这部分内存在哪分配,如何分配,则是JAVA虚拟机来决定。而这部分内存的释放,则是由自动内存管理系统(以下简称GC)来管理的。