1.字面量

字面量比较接近Java语言层面的常量概念。在java中,声明为finalintlongdoublechar等基本类型的常量值,特殊的字符串文本"abc"abc也是字面量。字面量一出生,其内容、大小全部固定,不会发生改变,编译时期存储在class文件的常量池中,可以在类加载后存放到方法区的运行时常量池当中。

2.符号引用

符号引用以一组符号来描述所引用的目标,符号引用可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可。例如,在Class文件中它以CONSTANT_Class_infoCONSTANT_Fieldref_infoCONSTANT_Methodref_info等类型的常量出现。符号引用与虚拟机布局无关,引用的目标不一定加载到内存中。在Java中,一个Java类将会被编译成一个class文件。在编译时,Java类并不知道引用的实际类的地址,因此只能使用符号引用来替代。比如People类引用了Language类,在编译时People类并不知道Language类的实际内存地址,因此只能使用符号Language来表示Language类的地址。各种虚拟机实现的内存布局可能有所不同,但是它们能接受的符号引用都是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。

符号引用属于编译原理方面的概念,主要包括下面几类常量:

  • 被模块导出或者开放的包(Package)
  • 类和接口的全限定名(Full Qualified Name)
  • 字段的名称和描述符(Descriptor)
  • 方法的名称和描述符
  • 方法的句柄和方法类型(Method Handle、Method Type、Invoke Dynamic)
  • 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)

3.直接引用

JVM 类加载过程中,解析阶段,Java虚拟机会把类的二级制数据中的符号引用替换为直接引用。

直接引用可以帮助程序直接定位到所需的对象

  • 直接指向目标的指针
  • 相对偏移量
  • 一个能够直接定位到目标的句柄

直接引用适合虚拟机的布局相关,同一个符号引用在不同的虚拟机上翻译出来的直接引用一般会不一致。如果有了直接引用,那么引用目标必定已经被加载到了内存当中。