JVM-专有名词
字节码
字节码的数据格式就是严格规定好,前0-3字节 是魔数,4-5字节 次版本号,6-7版本号,8-9常量池数量等。
为什么0-3一定是魔术,4-7是版本号,因为这就是约定好的,你按照这个格式写,我按照这个格式读。
符号引用和直接引用
符号引用:字符串,能根据这个字符串定位到指定的数据,比如java/lang/StringBuilder
直接引用:内存地址
虚拟机加载过程
虚拟机加载经历 加载--验证--准备--解析--初始化--使用--卸载
常量池
字面量
符号引用
- 类和接口的全限定名
- 字段名称和描述符
- 方法名称和描述符
类加载之后,常量池的内容会进入运行时常量池,这时候里面的数据也许还保持着符号引用。 (因为解析的时机由JVM自己设定) 如果在虚拟机栈的 栈帧中,我准备调用 main() 函数,那么会通过栈帧中持有的动态连接,找到运行时常量池, 然后找到main函数的常量 比如 #2 ,如果这个常量没有被解析过,那么就通过这个常量进行解析过程, 其中包括,通过常量 找到 类名 和 nameAndType,通过 nameAndType 找到方法名和返回值。 这时候 我手里有 类名/方法名/方法返回值,下一步,我通过类名和方法名,通过JVM记录的方法列表,找到对应的方法体。 而这个方法体实际上是一段内存地址,那么这时候我就把这段内存地址复制给 #2,并且给 #2设定一个已经解析的 flag。 这样就完成了 符号引用到直接引用的过程。
栈帧
动态链接
如果被调用的目标方法在编译期无法确定。这种情况下调用方法的符号引用转换为直接引用的过程称之为静态链接。
每一个栈帧内部都包含有一个指向运行时常量池 中该栈帧方法的引用。包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。例如invokednamic指令
在Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(Symbolic Reference)保存在class文件的常量池。
#开头的就是符号引用。
比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接调用
Q:为什么需要常量池?
A:字节码文件中需要很多数据的支持,但数据很大,不能直接保存到字节码文件中,所以常量池的作用就是为了提供一些符号和常量,便于指令的识别。