java符号引⽤_JAVA类的符号引⽤的理解
符号引⽤只是⼀些符号,包含在字节码⽂件的常量池中 它主要包括: 在该类中,出现过的各类包,类,接⼝,字段,⽅法等元素的全限定名有java类定义如下:
package Clazz;
import java.io.Serializable;
/**
* @Author : ZGQ
* @Date : 2020/3/25 9:56
* @Version : 1.0
*/
public class Rookie extends Person implements Serializable {
int myFiledCommon;
static int myFiledCommonStatic;
final static int myFiledCommonStaticFinal = 10086;
public void method1(){
int a = 1;
int b = 2;
int c = a+b;
}
public void method2(Person person){
System.out.println("THIS person OOPS");
}
private void method3(){
}
}
编译后,经javap⼯具反编译,常量池内容如下
Constant pool:
#1 = Methodref #6.#32 // Clazz/Person."":()V
#2 = Fieldref #33.#34 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #35 // THIS person OOPS
#4 = Methodref #36.#37 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #38 // Clazz/Rookie
#6 = Class #39 // Clazz/Person
#7 = Class #40 // java/io/Serializable
java类的概念#8 = Utf8 myFiledCommon
#9 = Utf8 I
#10 = Utf8 myFiledCommonStatic
#11 = Utf8 myFiledCommonStaticFinal
#12 = Utf8 ConstantValue
#13 = Integer 10086
#14 = Utf8
#15 = Utf8 ()V
#16 = Utf8 Code
#17 = Utf8 LineNumberTable
#18 = Utf8 LocalVariableTable
#19 = Utf8 this
#20 = Utf8 LClazz/Rookie;
#21 = Utf8 method1
#22 = Utf8 a
#23 = Utf8 b
#24 = Utf8 c
#25 = Utf8 method2
#26 = Utf8 (LClazz/Person;)V
#27 = Utf8 person
#28 = Utf8 LClazz/Person;
#29 = Utf8 method3
#30 = Utf8 SourceFile
#31 = Utf8 Rookie.java
#32 = NameAndType #14:#15 // "":()V
#33 = Class #41 // java/lang/System
#34 = NameAndType #42:#43 // out:Ljava/io/PrintStream;
#35 = Utf8 THIS person OOPS
#36 = Class #44 // java/io/PrintStream
#37 = NameAndType #45:#46 // println:(Ljava/lang/String;)V #38 = Utf8 Clazz/Rookie
#39 = Utf8 Clazz/Person
#40 = Utf8 java/io/Serializable
#41 = Utf8 java/lang/System
#42 = Utf8 out
#43 = Utf8 Ljava/io/PrintStream;
#44 = Utf8 java/io/PrintStream
#45 = Utf8 println
#46 = Utf8 (Ljava/lang/String;)V
反编译结果中,我们可以看到⼏个典型的符号引⽤,⽐如第⼀项为实例构造器,第四项为该类⽅法调⽤的其他⽅法,第六项为其⽗类
#1 = Methodref #6.#32 // Clazz/Person."":()V
#4 = Methodref #36.#37 // java/io/PrintStream.println:(Ljava/lang/String;)V
#6 = Class #39 // Clazz/Person
另外,⼀个类的⽣命周期中,共有七个阶段,分别是加载,验证,准备,解析,初始化,使⽤,卸载
其中,我们主要关⼼解析过程,因为这个过程的主要⼯作就是,将符号引⽤转化为直接引⽤. 解释直接引⽤之前,我们要先知道 所谓符号引⽤,只是⼀个符号⽽已,只是告知jvm,此类需要哪些调⽤⽅法,引⽤或者继承哪些类等等信息. 但是JVM在使⽤这些资源的时候,只有这些符号是不⾏的,必须详细知道这些资源的地址,才能正确地调⽤相关资源. 直接引⽤,就是这样⼀类指针,它直接指向⽬标. 解析过程,就是完成将符号引⽤转化为直接引⽤的过程,⽅便后续资源的调⽤.
JAVA中符号引⽤的出现是⾮常⾃然的,因为在类没有加载的时候,也不能确保其调⽤的资源被加载,更何况还有可能调⽤⾃⾝的⽅法或者字段.就算能确保,其调⽤的资源也不会每次在程序启动时,都加载在同⼀个地址. 简⽽⾔之,在编译阶段,字节码⽂件根本不知道这些资源在哪,所以根本没办法使⽤直接引⽤,于是只能使⽤符号引⽤代替.
然⽽,这只是解析的⼀部分,因为加载,验证,准备,解析,初始化这五步操作,实际上是类的初始化,换句话说,根本就没有实例对象产⽣. 所以,以上内容只对类加载时可以确定的符号引⽤进⾏解析,⽐如⽗类,接⼝,静态字段,调⽤的静态⽅法等 还有⼀部分,⽐如⽅法中的局部变量,实例字段等,他们什么时候开始解析呢.
很可惜,博主也不是全部知道(希望有⼀天能够划掉)
1.虚⽅法 和上⽅解析不同,上⽅的解析被称为静态解析 在调⽤虚⽅法(JVM中的概念)时,JVM只有运⾏
时才知道此⽅法指向的地址,所以此时必须⽤到动态连接,具体的实现⽅法就是分派 但是实际上,分派⼜分为静态分派和动态分派,静态分派实际上是属于静态解析的,⽤于⽅法的重载. 但是遇到⽅法重写时,便要⽤到动态分派了,来确定该虚⽅法的符号应⽤究竟是指向哪个地址.
2.静态⽅法中的⾮静态变量
3.⾮静态字段 ....
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论