🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] <br/> > ### `JVM`运行时数据区 * **程序计数器**`PC` * 线程私有,是一块很小的内存区域,存储了下一条需要执行的(JVM汇编)字节码的指令地址.每个线程都有自己的PC,记录了当前线程要执行的指令。 * **虚拟机栈**`VM Stack` * 线程私有,此栈中的元素叫做栈帧,线程在调用java方法时会为每一个元素创建一个栈帧,来存储**局部变量表,操作表,动态链接,方法出口**等信息 * 每个方法被调用和完成的过程,都对应一个栈帧从虚拟机栈上的入栈和出栈的过程。虚拟机栈的生命周期和虚拟机相同。 * 后入先出栈,线程调用对象方法时,JVM会创建一个栈帧放到虚拟机栈中,用来表示某个方法的调用,调用过程就是方法的入栈和出栈过程。 * **本地方法栈**`Native Method Stack` * 线程私有,功能和虚拟机栈相似,存储线程调用本地方法时,本地放法的局部变量表,操作栈等。 * **堆** `Heap` * Heap区被所有的线程共享,在虚拟机启动时创建。 * 存放对象实例,Heap区是垃圾回收管理的主要区域 * **方法区**`Method area` * 被所有线程共享,用于存储已经被虚拟机加载的**类信息,常量,静态变量**,即时编译器编译出来的代码等数据。 * ![](https://i.loli.net/2019/03/11/5c863d103d765.png) <br/> * ![](https://i.loli.net/2019/03/11/5c8677aa85c42.png) <br/> > ### 对象的创建 * 当`JVM`遇到一条`new`指令,首先检查这个指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。若没有,则先执行类的初始化过程。 * 类加载检查通过后,`JVM`为新生对象分配内存,对象所需内存大小在类加载完成后便可确定。分配内存有两种方式: * 指针碰撞,Java堆中内存是规整的 * 空闲列表,内存不规整,内存规整与否由垃圾收集器决定,CMS收集器是标记清除算法,内存不规整,所以采用空闲列表 * 内存分配完成后,`JVM`将舒适化的内存空间设置零值 * 设置对象头,如对象指向哪个类、类的元数据信息、对象的Hash码、对象的GC分代年龄、偏向锁等信息 * 执行对象的构造函数 <br/> > ### 类加载 ![](https://i.loli.net/2019/03/11/5c8643285a1bb.png)