jvm规范在运行java程序的过程会把它管理的区域分为若干区域(度娘图);
程序计数器(线程私有)*:*
是一块较小的内存空间,可以看做当前线程所执行的字节码行号的指示器;字节码解释器的作用就是通过改变计数器的值来选取下一条需要执行的指令,例如,循环,分支,跳转处理异常;都需要依赖这个计数器来完成。
Java虚拟机栈(线程私有):
每个方法在执行的同时,都会创建一个栈帧;来存储局部变量表(后续有详解),操作数栈,动态链接,方法出口等信息;每一个方法的调用到执行的过程对应栈帧在虚拟机中入栈,出栈的过程。
局部变量表存放了我们熟知的8种基本数据类型,boolean,byte,char,short,int,float,long,double.以及对象引用(强引用,弱引用,软引用,影子引用)等;注意的是;局部变量表所需要的内存空间在编译器就已经分配完成,当进入一个方法时,这个方法中局部变量所分配的内存空间是完全正确的;SO!方法在运行期间不会改变局部变量表的空间。
本地方法栈(Native Method Stack):
与虚拟机栈作用基本一致,区别是虚拟机栈执行的是java(字节码服务)服务,而本地方法栈虚拟机用到是Native本地方法服务;不做详解;
Java 堆(线程共享):
Java 虚拟机管理内存中最大的一块;Java 堆是被共享的一块内存区域。当虚拟机启动运行时,该区域存放我们new 出来的所有对象。包括对象,数组。
GC(垃圾回收机制)主要管理的也是该区域,包括为什么要有垃圾回收机制,什么对象需要回收,何时进行回收,如何进行回收,以及回收算法详解。
方法区(线程共享):
与Java 堆一样,是各个线程共享的区域,用于存储,已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码。为了跟Java 堆分开。取别名Non-Heap. 但大部分人称方法区为 “永久带”(Permanent - Generation),事实上,跟堆没什么鸟关系。只不过HotSpot虚拟机把GC的分代算法扩展至方法区,这样HotSpot虚拟机就可以像管理堆一样来管理方法区;
运行时常量(线程共享):
运行时常量是方法区一部分,所以也是线程共享。Class 文件中除了有类的版本,字段,方法,接口等信息,还有一项常量池(贼重要)用来存放编译期生成的字面量,和符号引用,这部分内容会在类加载后进入方法区的运行时常量池中存放。
Java虚拟机对Class文件,都有严格的规定 例如: 从版本号到次版本号再到常量个数等等都有严格的规定。
而且常量不一定只有编译期才能进入方法区;
直接内存:
并不是虚拟机运行时的一部分,也不是java虚拟机规范的内存区域;
但会被频繁使用
JDK NIO包中引入的通道(channel) ,与缓存区(buffer) 可以使用Native函数库直接分配内存。然后通过在Java堆中存储的一个叫做DirectBuffer对象作为引用进行操作,避免了直接在Java堆和Native堆中来回复制数据;
小结:
就个人而言,在JVM模型中最重要的就是 Java 堆,方法区;很多人侧重堆内存中内存的分配以及销毁。但我更着重的是方法区中的解析过程之后会对以上JVM运行区域,进行详解。