缘起
继续从读书笔记的角度来系统的学习《Advanced Design and Implementation of Virtual Machines》。这本书是英文编写,全部、认真、深入的读下来非常考验人。我之前也只是读了60%,而且越到后面越没有耐心。想了想,JVM在系统层面上要达到一定水准,可能还是得精读一到两本这样的书籍。记读书笔记是我学习知识和技能的一种比较好的方式,伴随我至少20多年了。暂且给这次的读书笔记取名“关于VM的理论”。
本篇介绍第III部分中的:
第九章“Garbage Collection Support”
第十章“Runtime Helpers”
第十一章“Exception-Throwing”
第十二章“Finalization and Weak References”
第十三章“Modularity Design of VM”
正式开始本篇之前,我有必要推荐一本书。
推荐一本书《深入理解Kotlin协程》
有个年轻的小伙伴Benny写了一本《深入理解Kotlin协程》的书。
书封皮最后有我写的推荐语,但很可惜是被阉割过的(我理解出版社编辑的做法,他们并不清楚技术人对技术观点,认识上的“反复无常”)。
如何正确看待协程?我个人是有一个相当大的转变的。先看推荐语的原文——
我最开始对kotlin和协程是比较“轻视”的,觉得它们无非是语法糖以及线程相关知识的新坛装旧酒。但随着我对JVM以及近些年来一些现代高级编程语言的深入学习,我突然意识到Kotlin其实远不只是基于Java,它天然就包含很多现代高级语言的特性。而协程在kotlin语言的加持下针对并发编程的痛点上更是进了一大步。很难得Benny能深入撰写一本这样的关于协程方面的论著。这本书并不简单,但值得各位读者深入学习。
其实,周志明老师在深入理解JVM最新版的书里也提到,协程很可能在Java后续版本得到支持,当然也是JDK里提供的——一个比较类似的例子就是C++11里STL搞了一个并发库一样。
本篇介绍什么
本篇内容见下图,对应原书中的第III部分最后的9到13章。
这几章内容看起来是相对比较痛苦的。痛苦的感觉是不知道讲了什么,不知道有什么用。所以,我们先大概说下这几章讨论的是什么问题。BTW,这几章之间的关联关系并不大,你可以选择感兴趣的阅读。
第九章Garbage Collection Support:主要讲JVM中如何实现对root对象的枚举。尤其是在遍历调用栈时,哪些寄存器里存的是对象这类问题。与之有关的一个经常碰到的词叫GC-Map。我在《深入理解Android JVM ART》一书里也简单的提到过这个对应的一个词叫StackMap。但这块内容非常复杂。
第十章Runtime-Helpers:看章节名称肯定是不知道在讲什么。Runtime-helper是书里经常提到的一个词,其根源是作者基于JVM模块化设计思路之上(第十三章Modularity Design of VM),将某些功能抽在一起集中研究。我在ART里并没有看到这样的一个单独模块。但与之有关的功能肯定是有的。比如,书中提到的Runtime-Helper,其价值在于“When Java code execution needs the VM-services, a runtime-helper is called that helpstransition the control from the Java world to the native world”。在这里,native word包括JNI层以及JVM自身的服务(例如抛异常,例如MONITORENTER的实现等)。另外,我想说下,这种划分是从模块化设计角度来看的,但离具体场景有些远,不太好学习(虽然这一章最后列了一些场景....)。这一章我不太想讲太多,比较干瘪。
第十一章"Exception-Throwing":这一章内容非常明确,就是将异常投递。我在研究ART里异常投递的时候,碰到的最大困难还是在于栈回溯和寄存器有关的内容。我曾经在去上海参加Droidconf 2018大会的火车上思考了好几个小时。当然,看了这本书之后我有了一些新的感受。上篇好像也提过,就是我们对汇编开发时对函数调用的不熟悉。如果有汇编写函数调用,栈都是要自己维护和处理的。哪些寄存器干什么用都是套路。只可惜我们对这些套路都不太了解。
第十二章"Finalization and Weak References"。专门介绍大GC领域里的"小众"知识。这个在ART一书里的"14.8 Java Reference对象的处理"一节中有非常详细的介绍。本文拟简单说几句
第十三章"Modularity Design of VM":以Apache Harmony为例介绍VM的模块化设计。这一章肯定不如我大ART那本书了,真刀实枪的干源码还是更直接点。要是没看过源码,光看书里写得这几页能学到什么?我打算介绍下ART里的各个模块。
ART里的各种模块
我把ART里(以写书的7.0为主)各种比较常见的模块列了下。相对来说,这些名字取得还是比较达意的,基本一看就能想到是干什么的
但是,你要说这些模块有没有“模块化的设计”?肯定有,也可能没有。什么意思呢?
肯定有:ART里有很多接口类,比如CodeGenerator、Assembler等。都可以通过接口类来解决不同CPU架构上的机器码生成。这肯定是解耦的,这是很明显的模块化的设计。
可能没有:所谓的抽象也只是行为的解耦,但数据结构解耦不了。数据结构如果无法解耦,完全意义上的模块化设计也做不到。说白了,模块和模块之间还是耦合很厉害。可惜这本书在第十三章“模块化设计”里说的都是行为上的模块化。但其实数据结构无法解耦导致了巨大的学习困难。
Soft-Reference对象回收顺序的考虑
关于Reference,本文不打算说太多基础知识,因为每个搞Java开发的,都自认为了解它。但正如我在ART一书第14章14.8节书里所说,“Java Reference是很多公司面试Java开发者时必问的知识点。从某种角度来看,这说明大家对JavaReference的知识是即熟悉又陌生。熟悉它的理由是大部分开发者都能说出几种Reference的差别以及各自适合的使用场景,而对它陌生的原因也很简单。毕竟,我们很少有机会能通过虚拟机的源代码来真正了解Reference。可以这么说,在没有看到源代码之前,我们只是知其然。看完源代码后,我们就能做到知其所以然”。