在准备阶段完成后,就进入了解析阶段。
解析阶段(Resolution),简言之,将类、接口、字段和方法的符号引用转为直接引用。
1、具体描述:
符号引用就是一些字面量的引用,和虚拟机的内部数据结构和内存布局无关。比较容易理解的就是在Class类文件中,通过常量池进行了大量的符号引用。但是在程序实际运行时,只有符号引用是不够的,比如当如下println()方法被调用时,系统需要明确知道该方法的位置。
举例:输出操作System.out.println()对应的字节码:
invokevirtual #24 <java/io/PrintStream.println>
以方法为例,Java虚拟机为每个类都准备了一张方法表,将其所有的方法都列在表中,当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法。
通过解析操作,符号引用就可以转变为目标方法在类中方法表中的位置,从而使得方法被成功调用。
2、小结:
所谓解析就是将符号引用转为直接引用,也就是得到类、字段、方法在内存中的指针或者偏移量。因此,可以说,如果直接引用存在,那么可以肯定系统中存在该类、方法或者字段。但只存在符号引用,不能确定系统中一定存在该结构。
不过Java虚拟机规范并没有明确要求解析阶段一定要按照顺序执行。在HosSpot VM中,加载、验证、准备和初始化会按照顺序有条不紊地执行,但链接阶段中的解析操作往往会伴随着JVM在执行完初始化之后再执行。
3、字符串的复习
最后,再来看一下CONSTANT_String的解析。由于字符串在程序开发中有着重要的作用,因此,有必要了解一下String在Java虚拟机中的处理。当在Java代码中直接使用字符串常量时,就会在类中出现CONSTANT_String
,它表示字符串常量,并且会引用一个CONSTANT_UTF8的常量项。在Java虚拟机内部运行中的常量池中,会维护一张字符串拘留表(intern),它会保存所有出现过的字符串常量,并且没有重复项。
只要CONSTANT_String形式出现的字符串也都会在这张表中。使用String.intern()方法可以得到一个字符串在拘留表中的引用,因为该表中没有重复项,所以任何字面相同的字符串的String.intern()方法返回总是相等的。
梦想很模糊,去追,它会渐变清晰。青春励志,奋斗下去别放弃。
网友评论