[Java] 开课吧--JVM (2)

动态链接:class文件中,一个方法调用其他方法,需要将方法的符号引用转化为内存地址的直接引用。类中调用父类方法,运行时执行子类方法(多态)

方法返回:把当前栈帧出栈。正常完成出口 / 异常完成出口

[Java] 开课吧--JVM

本地方法栈

直接操作硬件,C++方法

[Java] 开课吧--JVM

方法执行

先由Java编译器编译为Java字节码,再由Java解释器逐条解释,或对热点代码由JIT编译器编译运行

热点代码:被多次调用的方法;被多次执行的循环体

方法调用计数器:先检查是否存在已编译版本,否则方法调用次数加1,超过阈值则启动编译

加载存储指令

将一个局部变量表加载到操作数栈:load系列

将一个数值从操作数栈加载到局部变量表:store系列

将一个常量加载到操作数栈:const系列、push系列、ldc系列

[Java] 开课吧--JVM

 JIT运行方式

Server模式,Client模式

优化

公共子表达式消除

方法内联

逃逸分析(存在逃逸则无法优化)

栈上内存分配

标量替换

同步锁消除

方法调用

常见方法调用类型

私有方法:与类绑定,编译时确定

构造方法:与类绑定,编译时确定

静态方法:与类绑定,编译时确定

成员方法:不与类绑定,运行时确定

接口方法:不与类绑定,运行时确定

编译看左边,运行看右边

重载与重写

重写(overwrite):也叫方法覆盖,继承或实现关系下,子类和父类方法描述符(参数和返回值)一致,方法名称一致

重载(overloading):在同一个类中,方法名称一致,方法参数(类型和顺序)不一致,不关心返回值

可理解为运行时重新加载,即编译时按左边类,运行时才加载右边真正类型

静态绑定和动态绑定

通过类名、方法名、方法描述符识别方法

属性看左,方法看右

通过父类引用访问子类的属性,需要强制转型

方法调用指令

invokevirtual:调用非静态非私有方法(多态)

invokeinterface:调用接口方法(多态)

invokespecial:调用非静态私有方法、构造方法

invokestatic:调用静态方法

invokedynamic

方法调用过程

静态绑定方法:直接在运行时常量池找到引用

动态绑定方法:根据父类方法表确定要查找的方法索引(编译看左),从子类方法表中开始,找不到再去父方法表找

虚分配

Father father = new Son();

father指针指向son对象

根据本地变量表,找调用该虚方法的对象

取出对象头中的类型指针,找到Class对象

找到Class对象后,找到对应的虚方法表

找到对应的方法,进行方法调用

如果找不到,则去父类对象查找,最终找不到则报错

public class DynamicCall01 { public static void main(String[] args) { Father father = new Son(); // 多态,发生方法重载 father.f1(); // 打印结果: Son-f1() char c = 'a'; father.f1(c); // 打印结果: father-f1() para-int 97 } } // 被调用的父类 class Father { public void f1() { System.out.println("father-f1()"); } public void f1(int i) { System.out.println("father-f1() para-int " + i); } } // 被调用的子类 class Son extends Father { public void f1() { // 覆盖父类的方法 System.out.println("Son-f1()"); } public void f1(char c) { System.out.println("Son-s1() para-char " + c); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydgwp.html