个人随笔
目录
JVM(三)、符号引用、直接引用、静态链接、动态链接(浅析)
2021-02-26 22:18:00

符号引用

我们用命令javap -v Math.class 获取可读的字节码信息,如下

我们类信息中的所有符号都放在了常量池中,如下:

  1. ...
  2. public class com.suibibk.jvm.Math
  3. minor version: 0
  4. major version: 52
  5. flags: ACC_PUBLIC, ACC_SUPER
  6. Constant pool:
  7. #1 = Class #2 // com/suibibk/jvm/Math
  8. #2 = Utf8 com/suibibk/jvm/Math
  9. #3 = Class #4 // java/lang/Object
  10. #4 = Utf8 java/lang/Object
  11. #5 = Utf8 <init>
  12. #6 = Utf8 ()V
  13. #7 = Utf8 Code
  14. #8 = Methodref #3.#9 // java/lang/Object."<init>":()V
  15. #9 = NameAndType #5:#6 // "<init>":()V
  16. #10 = Utf8 LineNumberTable
  17. #11 = Utf8 LocalVariableTable
  18. #12 = Utf8 this
  19. #13 = Utf8 Lcom/suibibk/jvm/Math;
  20. #14 = Utf8 compute
  21. #15 = Utf8 ()I
  22. #16 = Utf8 a
  23. #17 = Utf8 I
  24. #18 = Utf8 b
  25. #19 = Utf8 c
  26. #20 = Utf8 main
  27. #21 = Utf8 ([Ljava/lang/String;)V
  28. #22 = Methodref #1.#9 // com/suibibk/jvm/Math."<init>":()V
  29. #23 = Methodref #1.#24 // com/suibibk/jvm/Math.compute:()I
  30. #24 = NameAndType #14:#15 // compute:()I
  31. #25 = Utf8 args
  32. #26 = Utf8 [Ljava/lang/String;
  33. #27 = Utf8 math
  34. #28 = Utf8 SourceFile
  35. #29 = Utf8 Math.java
  36. {
  37. public com.suibibk.jvm.Math();
  38. descriptor: ()V
  39. flags: ACC_PUBLIC
  40. Code:
  41. stack=1, locals=1, args_size=1
  42. 0: aload_0
  43. 1: invokespecial #8 // Method java/lang/Object."<init>":()V
  44. 4: return
  45. LineNumberTable:
  46. line 3: 0
  47. LocalVariableTable:
  48. Start Length Slot Name Signature
  49. 0 5 0 this Lcom/suibibk/jvm/Math;
  50. public int compute();
  51. descriptor: ()I
  52. flags: ACC_PUBLIC
  53. Code:
  54. stack=2, locals=4, args_size=1
  55. 0: iconst_1
  56. 1: istore_1
  57. 2: iconst_2
  58. 3: istore_2
  59. 4: iload_1
  60. 5: iload_2
  61. 6: iadd
  62. 7: bipush 10
  63. 9: imul
  64. 10: istore_3
  65. 11: iload_3
  66. 12: ireturn
  67. LineNumberTable:
  68. line 5: 0
  69. line 6: 2
  70. line 7: 4
  71. line 8: 11
  72. LocalVariableTable:
  73. Start Length Slot Name Signature
  74. 0 13 0 this Lcom/suibibk/jvm/Math;
  75. 2 11 1 a I
  76. 4 9 2 b I
  77. 11 2 3 c I
  78. public static void main(java.lang.String[]);
  79. descriptor: ([Ljava/lang/String;)V
  80. flags: ACC_PUBLIC, ACC_STATIC
  81. Code:
  82. stack=2, locals=2, args_size=1
  83. 0: new #1 // class com/suibibk/jvm/Math
  84. 3: dup
  85. 4: invokespecial #22 // Method "<init>":()V
  86. 7: astore_1
  87. 8: aload_1
  88. 9: invokevirtual #23 // Method compute:()I
  89. 12: pop
  90. 13: return
  91. LineNumberTable:
  92. line 11: 0
  93. line 12: 8
  94. line 13: 13
  95. LocalVariableTable:
  96. Start Length Slot Name Signature
  97. 0 14 0 args [Ljava/lang/String;
  98. 8 6 1 math Lcom/suibibk/jvm/Math;
  99. }

常量池中的就都是符号引用,那方法怎么找到。

符号引用转直接引用

我们再看一下我们的代码

  1. public class Math {
  2. private static Math math = new Math();
  3. public int compute() {
  4. int a = 1;
  5. int b = 2;
  6. int c = (a+b)*10;
  7. return c;
  8. }
  9. public static void main(String[] args) {
  10. Math math = new Math();
  11. math.compute();
  12. }
  13. }

在JVM执行到map.compute()时,也就是对于上面的指令

  1. 9: invokevirtual #23 // Method compute:()I

时,怎么根据符号引用找到compute()的执行指令?

我们通过#23去常量池中找到对应的符号

  1. #23 = Methodref #1.#24 // com/suibibk/jvm/Math.compute:()I

可以知道时方法引用,其实#23对应也有两个符号#1和#24,这两个符号分别如下

  1. #1 = Class #2 // com/suibibk/jvm/Math
  1. #24 = NameAndType #14:#15 // compute:()I

然后#24对应的时#14和#15

  1. #14 = Utf8 compute
  1. #15 = Utf8 ()I

所以#23对应的符号引用就是com/suibibk/jvm/Math.compute:()I
然后JVM会找到该符号引用对应的直接引用,放入栈帧的动态链接中。

静态链接

在类加载的解析阶段,会将符号引用替换为直接引用,该阶段会把一些
静态方法(符号引用比如main()方法)替换为指向数据所在内存的指针或句柄(直接引用),这就是所谓的
静态链接过程(在类的加载期间完成)

动态链接

动态链接就是指上面在程序运行期间把compute()方法的符号引用替换为直接引用的过程

 1684

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2