《深入理解Java虚拟机:JVM高级特性与最佳实践》第2版
第7章 虚拟机类加载机制
51. 类加载器
类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”动作放到 Java 虚拟机外部实现,以便让应用程序自己决定如何获取所需要的类。实现这个动作的代码模块称为“类加载器”。
52. 类加载器双亲委派模型 (Parents Delegation Model)
(“双亲”是 parents 的译法,其实并没有“双”的概念)
自定义类加载器(可能存在多个) -> 应用程序类加载器 (Application ClassLoader) -> 扩展类加载器(Extension ClassLoader)-> 启动类加载器 (Bootstrap ClassLoader)
类加载器之间的父子关系不是继承,而是子类使用组合关系复用父加载器。
当收到类加载请求,子类首先请求父加载器进行加载工作(一直向上传递直到启动类加载器),只有当父加载器无法完成加载(在它的搜索范围内没有找到所需的类)子加载器才会尝试自己加载。
第8章 虚拟机字节码执行引擎
53. 运行时栈帧结构
栈帧用于支持虚拟机进行方法调用和方法执行的数据结构。(虚拟机栈)
每个栈帧包括局部变量表、操作数栈、动态链接、方法返回地址和额外的附加信息。
54. 局部变量表
局部变量表以变量槽(Valriable Slot)为最小单位。
无论在32位机还是64位机,虚拟机都会使Slot在外观上表现为32位虚拟机。
对象是否被回收的根本原因是:局部变量表中的变量槽是否还存在关于该对象的引用。也就是说,即便 当java 代码里没有对象的引用,因没有对局部变量表读写操作,原引用的Slot没有被其他变量复用,所以 GCRoots 一部分局部变量表仍然保持着对它的关联。
建议此部分详细阅读原书 8.2.1,没有表面看起来那么简单。
55. 操作数栈
当一个方法刚刚开始执行的时候,这个方法的操作数栈是空的。在方法执行过程中,字节码指令会往操作数栈中写入和提取内容,也就是出栈 / 入栈。
56. 动态链接
Class 文件的常量池存有大量符号引用,字节码中方法的调用指令以常量池中指向方法的符号引用作为参数。
符号引用一部分在类加载阶段或者第一次使用时转化为直接引用——静态解析;
另一部分在每一次运行期间转化为直接引用——动态链接。
57. 方法返回地址
方法正常退出时,调用者的PC计数器的值可以作为返回地址,栈帧中很可能会保存这个计数器值;
方法异常退出时,返回地址通过异常处理器表确定,栈帧中一般不会保存这部分信息。
58. 附加信息
虚拟机规范允许具体虚拟机实现增加规范里没有描述的信息到栈帧中,例如与调试相关的信息,完全取决于具体实现。
未完待续...