JAVA的内存模型和内存区域
1、JAVA内存区域
方法区
方法区属于线程共享的内存区域,主要用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,根据Java 虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError 异常。
堆区
堆区是线程共享区域,在虚拟机启动时创建,是Java 虚拟机所管理的内存中最大的一块,主要用于存放对象实例,几乎所有的对象实例都在这里分配内存,也是垃圾收集器管理的主要区域,如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError 异常。
程序计数器
程序计数器是线程私有的数据区域,用来存储指向下一条指令的地址,也是即将要执行的指令代码。cpu会不停地做任务切换,这样必然导致经常中断和恢复。为了能够准确地记录各个线程正在执行的当前字节码指令地址,所以为每个线程都分配一个程序计数器。
虚拟机栈
每个方法执行时都会创建一个栈桢来存储方法的的变量表、操作数栈、动态链接方法、返回值、返回地址等信息。每个方法从调用直结束就对于一个栈桢在虚拟机栈中的入栈和出栈过程。
本地方法栈
本地方法栈属于线程私有的数据区域,这部分主要与虚拟机用到的 Native 方法相关,本地方法栈和java虚拟机栈十分相似,本地方法栈则是为了执行native方法所服务的,所以本地方法也是一个私有的内存区域,也是后进先出栈,作用是支撑native方法的调用。
2、JAVA内存模型
java内存模型与Java内存区域的划分是不同的概念层次,更恰当说JMM描述的是一组规则,通过这组规则控制 程序中各个变量在共享数据区域(方法区、堆区)和私有数据区域(程序计数器、虚拟机栈、本地方法栈)的访问方式,JMM是围绕原子性,有序性、可见性展开的。
主内存
主要存储的是Java实例对象,所有线程创建的实例对象都存放在主内存中,它包括了实例变量、静态变量和构成数组对象的元素,当然也包括了共享的类信息、常量。但是不包含局部变量与方法参数,由于是共享数据区域,多条线程对同一个变量进行访问可能会发现线程安全问题。
工作内存
主要存储当前方法的所有本地变量信息(工作内存中存储着主内存中的变量副本拷贝),每个线程只能访问 自己的工作内存,即线程中的本地变量对其它线程是不可见的,就算是两个线程执行的是同一段代码,它们也 会各自在自己的工作内存中创建属于当前线程的本地变量,当然也包括了字节码行号指示器、相关Native方法 的信息。注意由于工作内存是每个线程的私有数据,线程间无法相互访问工作内存,因此存储在工作内存的数 据不存在线程安全问题。