Java虚拟机内存分配
Java虚拟机在执行Java程序的过程中,会将它所管理的内存区域划分为几个不同的数据区域,这几个内存区域有的随着虚拟机进程的启动而存在,有的则依赖用户的线程的启动和结束而建立和销毁。Java虚拟机所管理的内存区域会将其管理的内存区域划分为以下几个运行时数据区域,方法区,堆区,虚拟机栈,本地方法栈,程序计数器五个部分如下图所示,其中方法区与堆区是进行垃圾回收的区域,虚拟机栈,本地方法栈,程序计数器这三个区域由于与线程相关,随着线程的启动和结束而建立和销毁,所以虚拟机不进行垃圾回收。
1.方法区
方法区是各个线程共享的数据区域,此区域主要存储类信息,常量,静态变量即时编译器编译的代码等数据信息,此存储区域是由全局共享的,此处的垃圾回收主要对常量以及已加载的类进行卸载的类进行回收。
2.堆区
堆区和方法区一样也是由全局共享的数据区域,在虚拟机启动时创建,此区域主要存储对象的实例与数组,因此此区域也是垃圾回收的重灾区,Java堆可以处于物理上不连续的内存空间中,只要是逻辑上连续的就可以。根据内存回收的角度来看,Java堆可以分为新生代和老生代两个区域。是垃圾回收的主要区域。
3.虚拟机栈
虚拟机栈是线程私有的区域,即每个线程都有其独有的虚拟机栈,它的生命周期与线程相同,虚拟机栈主要存储方法信息,每当调用一个方法时,虚拟机都会创建一个栈帧用来存放局部变量表,动态链接,方法出口信息等,每个方法从执行到完成的过程,实际上就是栈帧出栈入栈的过程。
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,如果扩展到无法申请足够的内存,就会抛出OutOfMemoryError异常。
4.本地方法栈
本地方法栈与虚拟机栈类似,唯一的不同则是,虚拟机栈处理执行的Java方法,而本地方法栈处理执行的是native方法。
5.程序计数器
程序计数器是一块较小的内存区域,可被看作是程序所执行的字节码的行号指示器,即可改变程序计数器的值知道下次该执行哪行代码,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个程序计数器。