Java字节码中invokespecial与invokevirtual指令的解析

1.invokespecial只能调用三类方法:<init>方法;私有方法;super.method()。因为这三类方法的调用对象在编译时就可以确定。

2.invokevirtual是一种动态分派的调用指令:也就是引用的类型并不能决定方法属于哪个类型。

看如下代码:

public class SubClass1 extends SuperClass{
	public static void main(String[] args){
		SubClass1 sb = new SubClass1();
		sb.commMethod();
	}
}

SubClass1的引用sb调用了commMethod方法,这个方法实际来自于SuperClass,我们将这段代码编译成字节码后是

Compiled from "SubClass1.java"
public class com.csii.parent.SubClass1 extends com.csii.parent.SuperClass
  SourceFile: "SubClass1.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class #2;//  com/csii/parent/SubClass1
const #2 = Asciz com/csii/parent/SubClass1;
const #3 = class #4;//  com/csii/parent/SuperClass
const #4 = Asciz com/csii/parent/SuperClass;
const #5 = Asciz <init>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Method #3.#9;//  com/csii/parent/SuperClass."<init>":()V
const #9 = NameAndType #5:#6;//  "<init>":()V
const #10 = Asciz LineNumberTable;
const #11 = Asciz LocalVariableTable;
const #12 = Asciz this;
const #13 = Asciz Lcom/csii/parent/SubClass1;;
const #14 = Asciz main;
const #15 = Asciz ([Ljava/lang/String;)V;
const #16 = Method #1.#9;//  com/csii/parent/SubClass1."<init>":()V
const #17 = Method#1.#18; //  com/csii/parent/SubClass1.commMethod:()V
const #18 = NameAndType #19:#6;//  commMethod:()V
const #19 = Asciz commMethod;
const #20 = Asciz args;
const #21 = Asciz [Ljava/lang/String;;
const #22 = Asciz sb;
const #23 = Asciz SourceFile;
const #24 = Asciz SubClass1.java;


{
public com.csii.parent.SubClass1();
  Code:
   Stack=1, Locals=1, Args_size=1
   0: aload_0
   1: invokespecial#8; //Method com/csii/parent/SuperClass."<init>":()V
   4: return
  LineNumberTable: 
   line 3: 0


  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       Lcom/csii/parent/SubClass1;




public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=2, Args_size=1
   0: new #1; //class com/csii/parent/SubClass1
   3: dup
   4: invokespecial#16; //Method "<init>":()V
   7: astore_1
   8: aload_1
   9: invokevirtual#17; //Method commMethod:()V
   12: return
  LineNumberTable: 
   line 9: 0
   line 10: 8
   line 11: 12


  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      13      0    args       [Ljava/lang/String;
   8      5      1    sb       Lcom/csii/parent/SubClass1;




}

可以看到引用sb.commMethod()编译后的字节码命令是invokevirtual,而字节码中调用方法也是com/csii/parent/SubClass1.commMethod:()V。没错,编译后字节码中显示它调用了子类的commMethod()方法,虚拟机运行这段代码时会动态绑定到SuperClass的commMethod方法上。

以上是子类继承并直接调用父类方法时编译的结果。若采用super.method()调用父类方法编译后将会采用invokespecial,这样执行的效率将会高一点。

另外,通过接口的引用调用方法时也会使用invokevirtual。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值