java虚拟机基础知识大全 java虚拟机运行原理( 四 )


Java虚拟机将常量池内的符号引用替换为直接引用的过程 。
符号引用与虚拟机实现的内存布局无关,引用的目标并不一定是已经加载到虚拟机内存当中的内容 。直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄 。直接引用是和虚拟机实现的内存布局直接相关
1.类或接口的解析
需要判断该类是否是数组类型
如果我们说一个D拥有C的访问权限,那就意味着以下3条规则中至少有其中一条成立:
·被访问类C是的,并且与访问类D处于同一个模块 。
·被访问类C是的,不与访问类D处于同一个模块,但是被访问类C的模块允许被访问类D的模块进行访问 。
·被访问类C不是的,但是它与访问类D处于同一个包中 。
2.字段解析
首先将会对字段表内[插图]项中索引的符号引用进行解析,也就是字段所属的类或接口的符号引用;
3.方法解析
先解析出方法表的[插图]项中索引的方法所属的类或接口的符号引用,如果解析成功,那么我们依然用C表示这个类 。
1)由于Class文件格式中类的方法和接口的方法符号引用的常量类型定义是分开的,如果在类的方法表中发现中索引的C是个接口的话,那就直接抛出java.lang.Error异常 。
2)如果通过了第一步,在类C中查找是否有简单名称和描述符都与目标相匹配的方法,如果有则返回这个方法的直接引用,查找结束 。
3)否则,在类C的父类中递归查找是否有简单名称和描述符都与目标相匹配的方法,如果有则返回这个方法的直接引用,查找结束 。
4)否则,在类C实现的接口列表及它们的父接口之中递归查找是否有简单名称和描述符都与目标相匹配的方法,如果存在匹配的方法,说明类C是一个抽象类,这时候查找结束,抛出java.lang.异常 。
5)否则,宣告方法查找失败,抛出java.lang. 。最后,如果查找过程成功返回了直接引用,将会对这个方法进行权限验证,如果发现不具备对此方法的访问权限,将抛出java.lang.异常 。
4.接口方法解析
方法解析类似
JDK 9中增加了接口的静态私有方法,也有了模块化的访问约束,所以从JDK 9起,接口方法的访问也完全有可能因访问权限控制而出现java.lang.异常 。
初始化阶段就是执行类构造器()方法的过程 。
·()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块({}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定的,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问 。
()方法与类的构造函数(即在虚拟机视角中的实例构造器()方法)不同,它不需要显式地调用父类构造器,Java虚拟机会保证在子类的()方法执行前,父类的()方法已经执行完毕 。因此在Java虚拟机中第一个被执行的()方法的类型肯定是java.lang. 。·由于父类的()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作 。
对于任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间 。
比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个Java虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等 。
这里所指的“相等”,包括代表类的Class对象的()方法、()方法、()方法的返回结果,也包括了使用关键字做对象所属关系判定等各种情况 。