首页 > 代码库 > java基础---JVM内存管理以及内存运行机制学习总结
java基础---JVM内存管理以及内存运行机制学习总结
自己从网上搜资料拼接了一张JVM内存图:如下图所示:
我们思考几个问题:
1.jVM是怎么运行的?
2.JVM运行时内存是怎么分配的?
3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区?
VM运行时数据区域:
1.程序计数器(program Counter Register):
是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的 方式去实 现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个 计数器来完成。
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核) 只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存 储,我们称这类内存区域为“线程私有”的内存。
如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空 (Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
2.java虚拟机栈(Java Virtual Machine Stacks):
里面存放的是本地变量表(存放了编译期可知的各种标量类型:Boolean,byte,char,short,int,float,long,double)、对象的引用(不是对象本身,仅仅是引用指针)、方法返回地址等。
虚拟栈中规定了两种异常状况:
- 如果线程请求的深度大于虚拟机所允许的深度,就会抛出stackoverflowerror异常,也就是栈溢出异常。在使用递归的调用方法的情况下,很容易抛出这个异常。
- 如果VM栈可以动态扩展,当扩展的时候无法申请到足够的内存空间,则抛出OutOfMemoryError异常,内存溢出。
3.本地方法栈(native method stacks)
这块区域在jvm运行内存中职责就相对比较少了。只是执行Native 方法。如果这个区的内存不足也是会抛出StackOverflowError 和 OutOfMemoryError 异常。
4.java 堆
这块区域是jvm中最大的一块区域了,java堆是被所有线程所共享的,也是GC主要的回收区,在jvm启动的时候就创建了。java堆的唯一的目的就是存放对象实例(所有new出来的对象)绝大部分对象的实例都是在这块区域分配。