首先看一下JVM的内存划分
方法区和堆属于线程共享区; 即所有线程共享方法区和堆的存储区域
虚拟机栈和本地方法栈及程序计数器属于线程独占区,即每个线程都会分配到内存用于虚拟机栈和本地方法栈及程序计数器
程序计数器
1.程序计数器位于线程独占区,是一块较小的内存空间,他可以看做是当前线程所执行的字节码的行号指示器
2.如果线程执行的是java方法,记录JVM字节码指令地址,如果执行native方法,值为undifined
3.唯一JVM中不会发生OO的区域(因为这块内存是JVM自己调度的)
虚拟机栈
1.虚拟机栈位于线程独享区,描述JAVA方法执行动态内存模型
每个方法执行都会创建一个栈帧,伴随方法从创建到完成,用于存储局部变量表,操作数栈,动态链接,方法出口等。
每个栈帧都推入虚拟机栈中,若当前方法A先调用A方法的栈帧先进栈,若方法A中调用了方法B,,方法B的栈帧再进栈,以此 类推,然后根据先进后出原则弹出虚拟机栈销毁,这就是JAVA方法执行的动态模型
2.局部变量表
< 存放编译器可知的各种基本数据类型,引用类型
< 局部变量表的内存空间在编译时完成分配,当进入一个方法时在栈帧分配的内存是固定的,在方法运行时期不会改变局部变量表的大小
<栈大小
若栈过深,会抛出Stack over flow
若栈帧的大小不做限制,可能会抛出OO
本地方法栈
位于线程独享区
<虚拟机栈为执行JAVA方法服务
<本地方法栈为执行native方法服务
堆
位于线程共享区
<存放对象实例
<垃圾收集器管理的主要区域
<新生代、老年代、Eden区域 (GC时细讲再理解)
<对象过多会抛出OO
方法区
<存储虚拟机加载的类信息(类版本,字段,方法,接口)、常量、静态变量,即时编译后的代码等数据
<在HotSpot中,为了省去管理方法区的代码,方法区等于永久代
<垃圾回收在方法区的行为
<异常定义
申请方法区异常抛出OO
<运行时常量池
维护一个不重复的字符串池,字符串过多时抛出OO