JVM内存模型
内存模型图
不管是什么程序,只要你想运行,必然都需要使用内存,在java家里,就需要java虚拟机专门设计内存的使用方式,java虚拟机在执行程序的过程中会把它所管理的内存划分为几个不同的区域。
如图:
java虚拟机管理的内存就是由图中几个运行时的数据区域组成,分为方法区、java堆、java栈、本地方法栈、程序计数器。
其中,java栈、本地方法栈和程序计数器是线程隔离的区域,也就是说,每个线程都各有自己的一份。
程序计数器
为了保证程序能够达到自动连续执行的效果,CPU必须要确定下一条指令的地址,所以,程序计数器又被称作指令计数器,也有称作PC寄存器的叫法。
我们可以把程序计数器看成当前线程所执行的字节码的行号指示器,虚拟机通过改变这个程序计数器的值来选取下一条需要执行的字节码指令。
对单核CPU来说,每一时刻只能有一个线程处于运行状态,直到当前线程执行完或者被挂起,让出CPU资源之后,才会轮到下一个线程进来运行。如果是多核CPU,是可以同时跑多线程的,线程与线程之间也是互不相干,当线程数量大于CPU数量时,也会和单核CPU一样进行一个轮训切换来分配资源,为了确保线程切换后能够恢复到正常的位置继续执行,每个线程就必须要有自己的程序计数器,程序计数器是线程独有的一块内存空间。
如果当前线程正在执行一个java方法,则程序计数器记录正在执行的java字节码地址,如果当前线程正在执行一个本地方法,那么程序计数器为空。
java栈
每一个线程都有一个私有的java栈,java栈在线程创建的时候被创建,其中保存着帧信息。(每个方法在执行的同时都会创建一个栈帧,用于保存局部变量、方法参数、方法出口等信息,每一个方法从调用到执行完成的过程,都对应着一个栈帧在java栈中入栈到出栈的过程)
简而言之,当线程调用java方法时,虚拟机会创建一个新的栈帧并且将其压入java栈。
栈的优势去访问速度比堆要快,仅次于程序计数器。
本地方法栈
本地方法栈和java栈非常类似,不同之处在于java栈用于java方法的调用,而本地方法栈用于本地方法的调用。
注意:本地方法栈不是用java实现的,而是使用C实现的。
java堆
堆在JVM启动的时候会被创建,我们可以把它理解成一个内存池,用来存放所有的java对象,所有的线程共享java堆。
方法区
方法区和堆一样是所有线程共享的区域,主要保存的信息是类的元数据,包括类的类型信息、常量、静态变量、域信息、方法信息等数据。
方法区中的信息来源于类装载子系统,类装载子系统加载class信息,加载到的东西就存放于方法区的内存空间。