JVM虚拟机内存组成:
如下图:
![](https://images2015.cnblogs.com/blog/1072224/201707/1072224-20170702203128758-1147995394.png)
1. 程序计数器:
(1)是一块较小的内存空间;可以看做当前程序执行子界面的行号指示器,字节码解析器执行的时候就是根据这个判断下一条指令该执行什么。
(2)因为cpu在执行代码的时候,会在多个线程之间进行切换执行,所以为了在cup切换后恢复到正确的执行位置,每条线程都有一个独立的程序计数器,各线程之间互不影响,独立存在,我们称此类内存为“线程私有”的内存。
(3) 如果当前cup执行的是java代码,这个计数器是记录的是正在执行的虚拟机字节码的地址;如果执行的native方法,这个计数器则为空(unfinished),此区域是虚拟机规定的唯一一个在java虚拟机规范中规定没有任何OutOfMemeryError情况的区域。
2. 虚拟机栈区:
(1)和程序计数器一样虚拟机栈也是线程私有的,它的生命周期和线程相同。
(2)其描述的java方法执行内存模型,每一个方法在执行的时候都会创建一个栈帧;用来存放局部变量,操作数栈,动态链接,方法出口,返回值;当一个方法开始执行到执行结束就是一个栈帧从入栈到出栈的过程。
(3)栈区对应两中异常: 当线程请求的栈深度大于虚拟机所允许的深度是,会抛出StackOverflowError异常;如果虚拟机的栈是可以动态扩展的,当扩展时申请不到足够的空间时,会抛出OutOfmemeryError。
3. 本地方法区:
(1)和虚拟机栈区非常相似,只是本地方法区是虚拟机调用native方法服务是的内存。
4. 虚拟机堆区:
(1) java程序中创建的实例队形都放在堆区, 是一个线程共享区。
(2) 堆区是垃圾回收器管理的主要区域,所以很时候也称为“GC堆”。
(3) 现在垃圾会收器大多数为分代回收,所以又分为“新生代”和“老年代”;“新生代”又可以分为eden区和survivor to 和 survivor from 区。
(4) 堆区可以是物理内存中不连续的空间,逻辑上连续就可以;可以是可扩展的也可以是固定的,如果是可扩展的,当创建对象分配内存的时候,无法申请到内存的时候就会抛出: OutOfmemeryError
(5) 设置堆内存的大小参数: -Xmx(最大),-Xms(最小)
5. 方法区:
(1) 和堆内存一样,是线程共享区;用于存储已被虚拟机加载的类信息,常量,静态变量。
参考资料: 深入理解Java虚拟机:JVM高级特性与最佳实践