Java学习之--虚拟机运行时戎码一生大纲虚拟机内部体系结构运行时基本流程方法表堆程序计数器Java栈执行引擎2020/1/31虚拟机内部体系结构方法区堆栈本地方法栈PC寄存器类装在子系统class文件执行引擎运行时数据区2020/1/31运行时的流程开始装载验证准备解析初始化执行方法结束垃圾回收2020/1/31运行时的流程-装载读取二进制流解析二进制流,并存入方法区•类型信息、字段、方法、常量池、类变量等创建一个该类型的java.lang.Class对象2020/1/31运行时的流程-验证语义验证比如:1.检查final的类不能被继承2.检查final的方法不能被重写3.检查超类和子类的方法的兼容性(是否出现同名方法,但是不是重载的情况)4.检查各常量池入口之间的一致性2020/1/31运行时的流程-准备类变量的内存分配类变量的默认值设置a为实例变量,初始化阶段该实例还未被创建。b为类变量,准备阶段分配内存,并设置默认值为0。2020/1/31运行时的流程-解析把符号引用替换成直接引用符号引用:和字节码中的信息基本类似。直接引用:1.指向类型、类变量和类方法的直接引用可能是指向方法区的本地指针。2.指向实例变量和实例方法的直接引用都是偏移量。2020/1/31运行时的流程-初始化初始化类变量的值有啥问题?2020/1/31运行时的流程-初始化初始化类变量的值•先超类,后子类•初始化阶段,通过调用clinit方法对类变量初始化语句和静态语句块进行初始化•类变量初始化语句和静态语句块的执行优先级是相同的,按照Java源代码中的顺序一次执行•实例变量不在这个阶段进行初始化,而是在new操作的时候调用init方法进行初始化类变量初始化语句://publicstaticintstaticInt;不是类变量初始化语句publicstaticintstaticInt=5;publicstaticdoublec=Math.random()*0.3;静态语句块:static{。。。。。}2020/1/31类初始化:clinit方法2020/1/31实例初始化:init方法2020/1/31方法表-方法查找2020/1/31方法表-方法查找虚拟机规范没有规定必须有方法表(方法表需要额外的内存)在字节码装载的时候存放到方法区中私有方法和实例初始化方法调用指令:invokespecial静态方法的调用指令:invokestatic每个类都有一个方法表,方法表包含从超类继承来的实例方法方法表中的方法是非私有、非静态、非初始化的实例方法•方法表可以理解为一个指针数组,每个元素指向方法区中的某个方法•实例方法调用指令:invokevirtual•接口方法调用指令:invokeinterface•每个堆中的实例都有一个指向方法区的指针都说接口方法调用比实例方法慢,为什么why?2020/1/31方法表-Dog的方法表2020/1/31方法表-CockerSpaniel的方法表2020/1/31方法表-Dog的方法表2020/1/31堆堆用来存储创建的实例(对象、数组)有分配新对象的指令,但没有释放对象内存的指令,释放内存完全交由垃圾收集器来做一个Java程序一个Java虚拟机实例,一个Java虚拟机实例一个堆虚拟机或者Java程序之间的堆互不干扰,但同一个Java程序中的不同线程共享堆堆空间不一定是连续的内存区,可动态伸缩2020/1/31堆-实现1指向对象池的指针指向类数据的指针堆句柄对象实例数据对象锁、等待集合垃圾收集相关数据。。。。。。方法区类数据类数据类数据类数据类数据。。。指向句柄池的指针。。。一个对象的引用2020/1/31堆-实现2指向类数据的指针实例数据堆方法区类数据类数据类数据类数据类数据。。。指向堆的指针。。。一个对象的引用对象锁、等待集合垃圾收集相关数据。。。。对象2020/1/31程序计数器每个线程一个程序计数器总是指向下一条指令(在调用方法返回的时候是指向哪儿?)在方法内跳转的时候会用到程序计数器,比如:gotofff9(程序计数器的值-7等于下一跳指令的位置)程序计数器还有啥作用?2020/1/31Java栈往Java栈中压栈和出栈的目标是栈帧每调用一个方法就创建一个栈帧Java栈通常是预先分配一个较长的内存空间,当空间不够的时候再扩展Java栈栈帧(与方法对应)•局部变量区(存放方法参数和方法体中的局部变量,生命周期短)•操作数栈(栈帧中的栈,用于指令操作数存储,生命周期短)•帧数据区(存放常量池指针、异常表的引用、调试数据、支持方法正常返回)2020/1/31Java栈Main类main()栈帧Main类main()栈帧ClassA类init栈帧Main类main()栈帧ClassA类callClassBMethod()栈帧Main类main()栈帧ClassA类callClassBMethod()栈帧ClassB类call()栈帧Main类main()栈帧ClassA类callClassBMethod()栈帧ClassB类call()栈帧PrintStream类println()栈帧Main类main()栈帧Main类main()栈帧ClassA类callClassBMethod()栈帧ClassB类call()栈帧。。。。栈底栈顶init完成,出栈println()完成,出栈call()完成,出栈callClassBMethod()和main()依次出栈2020/1/31Java栈-栈帧a指向常量池的指针局部变量区帧数据区异常表的引用调试数据支持方法返回等等bcdghefthis操作数栈01234579102020/1/31Java栈-栈帧this引用帧数据区1result88.88帧数据区addAndPrint()的栈帧addTwoTypes()的栈帧0101Java栈中紧凑的布局2020/1/31Reference《深入Java虚拟机》Java虚拟机规范百度2020/1/31谢谢内容纯属虚构,具体请看源码希望后续能有更实用的虚拟机解读