目录

ThasBlog

学无止境

X

Java 方法调用的底层实现

Java 方法调用通过字节码指令 invokestatic, invokespecial, invokevirtual, invokeinterface, invokedynamic 来实现方法调用.

非虚方法

非虚方法指能够在运行时直接确定其调用地址的方法, 这些方法在类加载完成之后, 其内存地址都是不会再变化的, 可以直接访问调用.

invokestatic: 静态方法调用

invokespecial: 私有实例方法调用, 构造方法或 super 方法, 被 final 修饰的实例方法

虚方法

由于多态的特性, 方法可以被不同的子类覆写, 所以对于同一个方法, 它们的实现不同, 对应的方法的目标地址也是不一样的, 通过查方法表来实现动态调用.

invokevirtual: 可被覆写的实例方法, 大部分调用方法都是这种方式. Java 对象的方法表存放在类中(与 C++不相同), 从对象实际类型开始递归向上查找类型的方法表, 第一次执行过后, 以方法位置作为索引编号建立缓存

invokeinterface: 类似invokevirtual, 但比较慢, 因为接口中方法的位置编号是无法确定的(不同的类都可以实现这个接口), 所以命中不了缓存

invokedynamic: 调用动态方法.

比如 lambda, lambda方法体会编译成当前类的一个方法, 如果方法体没有使用任何实例变量或方法, 则会编译成一个静态方法, 否则编译成一个私有的实例方法. 如果是方法引用(::), 则不需要生成该方法.

通过 invokedynamic 指令创建一个方法句柄, 这个方法句柄执行时会调用创建匿名类的对象的静态方法. 具体原理参考源码 https://github.com/ThasGit/java-learning/blob/master/src/main/java/cc/thas/lambda/LambdaMain.java


标题:Java 方法调用的底层实现
作者:thas
地址:https://thas.cc/articles/2021/04/09/1617954923009.html