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

#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.非静态字段 ....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值