java内存区域模型和详解
一,概述
java虚拟机运行时数据区模型图:
主要包括:程序计数器,java虚拟机栈,本地方法栈,java 堆,方法区(元空间)。
其中堆和方法区由所有线程共享的数据区;程序计数器,java虚拟机栈,本地方法栈是线程隔离的数据区。
二,程序计数器
程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。在java概念模型中,字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
每条线程的计数器都是独立的,互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
通俗来讲,例如:就是一个A方法(线程)运行到第10行代码,这个时候有一个B线程获取了CPU资源,这个时候在A的字节码处做一个标记,下次再轮到A的时候就不需要再重复执行之前的代码。不过这些都是在字节码(.class文件)层面,在此处只是通俗打个比方。
三,栈
栈是线程私有的,在每个方法执行的时候,会同步创建一个栈帧,用于存储局部变量表,操作数栈,动态连接,方法出口等信息。
在大部分的情况下,我们说的“栈”指的是就是局部变量表部分。局部变量表存放了编译前的java基本数据类型,对象引用和returnAddress 类型
栈区域出现异常的情况:
1.如果线程请求的栈深度大于虚拟机所应许的深度,将抛出StackOverflowError 异常。
2.如果java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError 异常。
四,本地方法栈
本地方法栈与栈发挥的作用差不多,栈是为 java方法(字节码) 服务,而本地方法栈是为虚拟机使用到的本地(Native)方法服务。
本地方法栈区域出现异常的情况:本地方法栈也会在栈深度和栈扩展失败的时候分别抛出:StackOverflowError 和 OutOfMemoryError 异常。
五,java 堆
1,java堆是内存共享的,也是虚拟机所管理内存最大的一块。java世界里 “几乎” 所有的对象实例都是在这内存中进行分配
2, java 堆是垃圾收集器管理的内存区域,因此也被称为 “GC堆”
3,从分配内存的角度看,所有的线程共享的java 堆 可以划分为许多线程私有分配缓冲区,以提高对象分配时的效率。
4,java 堆可以在物理上内存空间是不连续的,但在逻辑上应该是被视为连续的。
5,java 堆可以被固定为现成大小,也可以进行扩展
栈区域出现异常的情况:
1.如果在 java 堆中没有内存完成实例的分配,并且堆也无法进行扩展时,java 虚拟机会抛出 OutOfMemoryError 异常。
六,方法区
概念:方法区也是线程共享的内存区域,它用于存储被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。
方法区可以像堆一样,可以进行扩展和在物理上不连续,还可以选择不实现垃圾收集。
方法区出现异常的情况:
1.如果方法区无法满足新的内存分配需求时,将抛出 OutOfMemoryError 异常。