Fari

java中的动态链接

以下为我个人的理解:

在java中,有两个地方会提到动态链接,一不小心弄混了就会非常困惑

一个过程

假设我写了两个方法:

method2的字节码指令为:

其中 invokevirtual 表示执行的是一个虚方法,所谓虚方法,就是只有代码在运行期间才知道真正调用的是哪个方法(final 修饰的方法除外),而不是在编译期间就确定的。

后面的 #7 指的是常量池中字符串常量的引用,将引用具体化可以得到 Method method1:()I,后面得到的这一串字符就是符号引用

为什么这里执行 method1 是一个虚方法?因为你不确定子类或者父类是否重写了该方法,所以编译期间你根本不知道它调用的到底是哪个方法。只有真正运行后,知道是哪个对象调用的该方法后才能确定应该调用谁的方法

所以在真正调用该方法前,这个被调用的方法仅仅是一个符号引用,每次只有真正调用该方法时,才会将该引用转换为所调用方法的直接引用,这个运行时才确定直接引用的过程,就称之为动态链接。

注意:这里的动态链接是一个过程,或者说是一种思想

一个引用

JVM会在调用每一个方法前,都在方法栈头创建一个栈帧,该栈帧是一种能够支持函数调用所有信息的数据结构,它是一个具体的存在。

而栈帧中会保存一个指向常量池的指针,该指针实际指向常量池中该方法的实际引用。这个指针就是动态链接。

注意:这里的动态链接是一个指针,它是一个有形的实体

方法在调用时不是已经确定了自己的引用吗,为什么还要保存自己的引用?

  1. 便于获取栈信息:例如我们在debug或者保存栈快照时,它能告诉我们栈中到底有哪些函数

  2. 函数结束执行后可以知道它的返回值是哪个方法返回的

  3. 另一种说法是方法在调用时并不会一次性加载所有的方法信息,例如异常表等,只有真正出现异常后才去方法区加载该方法的异常表,那么这个过程肯定得知道该方法到底属于方法区的哪个方法。

参考:http://rabbit.eng.miami.edu/class/519/frames.html#:~:text=Stack%20Frames%20are%20an%20implementation,record%20is%20currently%20in%20use.

引自上文:Often, it is better to take a more abstract and high-level view of things. An Activation Record is a data structure that holds all the information needed to support one call of a function. It contains all the local variables of that function, and a reference (or pointer) to another activation record; that pointer is known as the Dynamic Link. Stack Frames are an implementation of Activation Records. The dynamic link corresponds to the “saved FP” entry; it tells you which activation record to return to when the current function is finished. The frame pointer itself is simply a way of indicating which activation record is currently in use. The dynamic links tie all the activation records for a program together in one long linked list, showing the order they would appear in a stack.

https://stackoverflow.com/questions/35550168/why-is-dynamic-link-required-in-function-activation-record-in-static-scoped-la

注:这个问题是关于c语言的,但其问题是栈帧中指向自己引用的指针的作用,和java的应该差不多

Tags: