【问题标题】:Java Class file and method bindingJava 类文件和方法绑定
【发布时间】:2018-12-14 08:13:17
【问题描述】:
public class Bike {
 void run() {
   System.out.println("bike is running");
 }
}

public class Honda extends Bike{
 public static void main(String[] args) {
   Honda h = new Honda();
   h.run(); // output 'bike is running'
 }
}

我尝试查看 Honda 类的类文件,下面是 main 方法的字节码

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=2, args_size=1
     0: new           #1                  // class newpackage/Honda
     3: dup
     4: invokespecial #16                 // Method "<init>":()V
     7: astore_1
     8: aload_1
     9: invokevirtual #17                 // Method run:()V
    12: return

在第 9 行指定了要调用的方法,常量池中的 #17 条目解析如下

#17 = Methodref          #1.#18         // newpackage/Honda.run:()V
#18 = NameAndType        #19:#6         // run:()V

我期待 #17 解析为 Bike.run 而不是 Honda.run,因为在编译时,父类中存在 run 方法的信息是可用的。 这里发生了什么?

【问题讨论】:

  • 我的猜想:支持 HotSpot 交换 #17 Honda.run 是 Bike.run 的同义词。但是,如果突然可以使用 Honda.run 的实现(无需重新启动 JVM),则不需要更改字节码。 #17 现在指向 Honda.run 实现,而不是 Bike.run 的同义词。所以更新了JVM的vtable,而不是需要更新的字节码。

标签: java methods


【解决方案1】:

在不重新编译子类的情况下,基类可能会发生变化。

要执行该方法,在运行时声明run() 的位置无关紧要,只要仍然存在这样的继承 方法即可。 (如果没有,你会得到NoSuchMethodError

如果编译器将#17 定义为Bike.run(),则代码将过于依赖Bike 类。

【讨论】:

  • 所以在运行时,当 JVM 到达第 9 行时,它会找到 invokevirtual 并转到 #17 并看到它解析为 Honda.run() 并尝试在 Honda 类中找到 run() 方法,当它没有'找不到它JVM开始搜索父类run()方法?
  • @cloud 是的。阅读invokevirtual的规范了解更多详情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多