硬核万字长文,深入理解 Java 字节码指令(建议收藏) (4)

举例来说。

public class Writer {
    private String name;
    static String mark = "作者";

    public static void main(String[] args) {
        print(mark);
        Writer w = new Writer();
        print(w.name);
    }

    public static void print(String arg) {
        System.out.println(arg);
    }
}

通过 jclasslib 看一下 main() 方法的字节码指令。

硬核万字长文,深入理解 Java 字节码指令(建议收藏)

getstatic #2 ,访问静态变量 mark

getfield #6 ,访问成员变量 name

05、方法调用和返回指令

方法调用指令有 5 个,分别用于不同的场景:

invokevirtual:用于调用对象的成员方法,根据对象的实际类型进行分派,支持多态。

invokeinterface:用于调用接口方法,会在运行时搜索由特定对象实现的接口方法进行调用。

invokespecial:用于调用一些需要特殊处理的方法,包括构造方法、私有方法和父类方法。

invokestatic:用于调用静态方法。

invokedynamic:用于在运行时动态解析出调用点限定符所引用的方法,并执行。

举例来说。

public class InvokeExamples {
    private void run() {
        List ls = new ArrayList();
        ls.add("难顶");

        ArrayList als = new ArrayList();
        als.add("学不动了");
    }

    public static void print() {
        System.out.println("invokestatic");
    }

    public static void main(String[] args) {
        print();
        InvokeExamples invoke = new InvokeExamples();
        invoke.run();
    }
}

我们用 javap -c InvokeExamples.class 来反编译一下。

Compiled from "InvokeExamples.java"
public class com.itwanger.jvm.InvokeExamples {
  public com.itwanger.jvm.InvokeExamples();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4return

  private void run();
    Code:
       0new           #2                  // class java/util/ArrayList
       3: dup
       4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #4                  // String 难顶
      11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      16: pop
      17new           #2                  // class java/util/ArrayList
      20: dup
      21: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
      24: astore_2
      25: aload_2
      26: ldc           #6                  // String 学不动了
      28: invokevirtual #7                  // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      31: pop
      32return

  public static void print();
    Code:
       0: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #9                  // String invokestatic
       5: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8return

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #11                 // Method print:()V
       3new           #12                 // class com/itwanger/jvm/InvokeExamples
       6: dup
       7: invokespecial #13                 // Method "<init>":()V
      10: astore_1
      11: aload_1
      12: invokevirtual #14                 // Method run:()V
      15return
}

InvokeExamples 类有 4 个方法,包括缺省的构造方法在内。

1)InvokeExamples() 构造方法中

缺省的构造方法内部会调用超类 Object 的初始化构造方法:

`invokespecial #1 // Method java/lang/Object."<init>":()V`

2)成员方法 run() 中

invokeinterface #5,  2  // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z

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

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