Kris Mok, Software Engineer, Taobao
@rednaxelafx
莫枢 /“撒迦”
为啥别读HotSpot VM的源码

   第0次JVM源码阅读活动


             阿里巴巴集团-技术共享平台-
              核心系统研发-专用计算组
                    莫枢(撒迦)
                     2012-03-03
关于我…
•   2009年毕业自南京大学软件学院
•   同年10月加入淘宝
•   目前在参与JVM相关研发
•   编程语言的设计与实现爱好者

• 希望与各位同好多交流!
    –   博客: http://rednaxelafx.iteye.com/
    –   新浪微博: http://weibo.com/rednaxelafx
    –   高级语言虚拟机群组: http://hllvm.group.iteye.com/
    –   JVM源码阅读活动微群: http://q.weibo.com/1823766
分享目标(I)
• 让VM相关基础知识尚浅的人找到阅读
  HotSpot VM源码之外的学习JVM的路径

• 让并不真的对VM内部实现细节感兴趣的人
  不必在源码上耗费精力
分享目标(II)
• 为后续活动做准备
 – 确定活动周期、形式、目标受众
 – 吸引同好报名分享阅读VM源码的经验
突击提问
•   已读过或正在读OpenJDK的源码?
•   已读过或正在读其它VM的源码?
•   有兴趣自己动手实现VM?
•   有编译器/解释器的实现经验?
突击提问(II)
• PermGen
 – a. 不知道是什么?
 – b. 在“堆内”?
 – c. 在“堆外”?
 – d. 不关心?
为啥要读HotSpot VM的源码?
• 生产环境使用Oracle/Sun JDK或OpenJDK
 – 读源码有助解决问题(真能么?)
• 三大主流高性能JVM中唯一开源的
 – 另外两个的源码也读不到
• 想修炼内功
 – “现实”驱动还是真感兴趣?
• 找点乐子
• 其它
读HotSpot VM源码想了解什么?
• JVM crash了!为什么?怎么办?
• JVM报OutOfMemoryError了 …

• 想学习如何操纵字节码
• “这段代码创建了多少个对象”?
• “JVM会让String共享char[]”?

• 其它
理想与现实(I)



例子:
JVM的架构与知识点
概念中JVM的结构
             类加载器
Class文件       子系统




             内存空间
                                 自动内存
                          本地      管理
   方法区    Java堆   Java栈
                          方法栈

地址        数据
          和指令

 指令计数器
                          本地方法
 以及其它        执行引擎          接口
                                 本地方法库
 隐含寄存器
某个JVM实现的架构
HotSpot Server Compiler的优化
理想与现实(II)



例子:
iadd字节码指令的实现
例:概念
                      3) add
             value1 + value2

                  1) pop       4) push

value2

         2) pop                value1 +
value1                         value2




         JVM规范所规定的抽象行为
例:理想——简单直观
case SVM_INSTRUCTION_IADD: {
  /* instruction body */
  jint value1 = stack[stack_size - 2].jint; ②
  jint value2 = stack[--stack_size].jint;①
  stack[stack_size - 1].jint = value1 + value2;
                   ④                  ③
  /* dispatch */
  goto dispatch;
}


          取自SableVM的switch版解释器
          (sablevm/src/libsablevm/instructions_switch.c)
例:现实——简单但不那么直观


                        ①
                        ②

              ④     ③




       取自早期版本Maxine VM的模板JIT编译器
例:现实——有点绕弯
void TemplateTable::iop2(Operation op) {
  transition(itos, itos);
  switch (op) {
  case add :                     __ pop_i(rdx); __ addl (rax, rdx);
break;
  case sub : __ movl(rdx, rax); __ pop_i(rax); __ subl (rax, rdx);
break;
  case mul :                     __ pop_i(rdx); __ imull(rax, rdx);
break;
  case _and :                    __ pop_i(rdx); __ andl (rax, rdx);
break;
  case _or :                     __ pop_i(rdx); __ orl (rax, rdx);
break;
  case _xor :                    __ pop_i(rdx); __ xorl (rax, rdx);
break;
            取自HotSpot VM的模板解释器,AMD64版
  case shl : __ movl(rcx, rax); __ pop_i(rax); __ shll (rax);
break;
  case shr : __ movl(rcx, rax); __ pop_i(rax); __ sarl (rax);
break;
  case ushr : __ movl(rcx, rax); __ pop_i(rax); __ shrl (rax);
例:现实——很多细节
void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right,
    LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) {
  if (left->is_single_cpu()) {
    Register lreg = left->as_register();
    if (right->is_single_cpu()) {
      // cpu register - cpu register
      Register rreg = right->as_register();
      switch (code) {
        case lir_add: __ addl (lreg, rreg); break;
        // ...                                          取自HotSpot VM的
                                                  Client编译器,AMD64版
      }
    } else if (right->is_stack()) {
      // cpu register - stack
      Address raddr = frame_map()->
                        address_for_slot(right->single_stack_ix());
      switch (code) {
        case lir_add: __ addl(lreg, raddr); break;
        // ...
      }
    } else if (right->is_constant()) {
      // cpu register - constant
      jint c = right->as_constant_ptr()->as_jint();
      switch (code) {
        case lir_add: __ incrementl(lreg, c); break;
        // ...
      }
learn JVM without reading HotSpot VM’s source code

不读HOTSPOT VM的源码
为何不要读HotSpot VM的源码?

• 基础概念不扎实时
 – 硬读复杂实现的源码对理解基础概念帮助不大
 – 繁琐的实现细节反而会掩盖掉一些抽像概念
• 已有现成的阅读资料时
 – 读资料比读源码更容易吸收自己需要的信息
  • 因人而异
• 可参加“源码阅读活动”
 – 让别人读源码,等分享…?
不明就里读源码的坏处?

• 加深误解
 – 案例1:HotSpot VM的解释器是这样实现的!
   • 主流平台上的HotSpot VM使用“模板解释器”,而非这里
     说的“C++解释器”
 – 案例2:HotSpot VM用内部地址实现Java对象的
   hashCode()!
   • oopDesc才是HotSpot VM中表示Java对象的类型;
     ciObject不是
• 浪费时间/精力
 – 读了但全然无法理解,还不如先不读
 – 有些细节知道了也没用(视目的而异)
如何不读HotSpot VM的源码

• 仅为了理解Java程序的行为?
 – 是否已了解Java语言层面的规定?
  • 否 => 先读Java语言规范
 – 是否已了解JVM的抽像概念?
  • 否 => 先读JVM规范
 – 已确定想关注的行为是特定于某个实现?
  • 否 => 回到前面两点
 – 是否有关于该实现的行为的文字描述?
  • 是 => 先读文字描述
  • 否 => 那…真的要读源码么?
如何不读HotSpot VM的源码(续)

• 仍然想深入学习VM的内部知识?
 – 阅读相关背景知识的书、论文、博客等
  • 能够(在读源码前)事先了解许多术语
  • 知道术语便于找到更多资料
 – 阅读更简单一些的VM实现的源码
  • 循序渐进
 – 自己动手写简单的编译器/VM
  • 实践是检验真理的唯一标准
 – 最后…
  • 如果真的很有空才去读HotSpot VM的源码
如何不读HotSpot VM的源码(续)

• 工作就是鼓捣HotSpot VM的内部?
 – 那真的得读代码,而且还得非常仔细地读
 – 但动态调试比静态阅读代码更有助形象地理解
 – 入手顺序
   • 文档
   • 读代码
   • 做实验+调试
alternative JVMs

其它JVM
KVM
• 项目主页:
 – http://java.sun.com/products/cldc/
• 介绍:
 – http://java.sun.com/products/cldc/wp/




             简单小巧的JVM
KVM (续)
• 好处
 – 包含JVM的最核心组件
 – 实现方式与JVM规范所描述的抽象的JVM相近
• 坏处
 – 是Java ME CLDC VM,而不是Java SE VM
 – 未实现反射、浮点数计算等功能
Maxine VM
• 项目主页:
 – http://labs.oracle.com/projects/maxine/
• 介绍:
 – https://wikis.oracle.com/download/attachment
   s/4161575/The+Maxine+Virtual+Machine.pdf



            纯Java实现的JVM
Maxine VM(续)
• 可在IDE里开发和调试
• 二进制兼容性
 – 可使用Oracle JDK/OpenJDK的类库,兼容主
   流Java应用
Maxine VM(续)
• 与HotSpot VM的部分对应关系
 – 对HotSpot Client Compiler(C1)感兴趣的,
   可以读Maxine VM里的C1X来帮助理解
   • 可通过C1Visualizer以图形界面更好的理解该编译器
     的设计
 – 对HotSpot Server Compiler(C2)里的中间表
   现形式(Sea-of-nodes IR)感兴趣的,可以读
   Maxine VM里的Graal来帮助理解
   • 可通过IdealGraphVisualizer以图形界面理解该编译
     器的设计
演示:Maxine Inspector
演示:C1Visualizer
演示:IdealGraphVisualizer
VMKit / J3
• 项目主页:
  – http://vmkit.llvm.org/
• LLVM + MMTk + GNU Classpath




       现成组件搭积木实现的JVM
其它项目
• 其它值得阅读源码的            • 其它值得阅读源码的
  JVM                    非JVM项目
 –   Jikes RVM / MRP    – ASM
 –   JamVM
 –   cacaovm           • 其它值得实验的项目
 –   SableVM            – BiteScript
recommended reading

推荐阅读
VM相关书堆…
我读过的VM相关书
• 请参考豆瓣页面
  http://book.douban.com/people/Rednaxela
  FX/all?tag=VM
• 基础知识主要靠这些书获得,通过自己写
  代码来理解
• 但比较深入的知识通常是从论文而不是书
  中获得的
• Anyway,规范一定要读!
计算机系统概论
• http://book.douban.com/subject/2185076/
深入理解计算机系统
• http://book.douban.com/subject/5407246/
程序设计语言——实践之路
• http://book.douban.com/subject/2152385/
虚拟机——系统与进程的通用平台

• http://book.douban.com/subject/1885761/
游戏脚本高级编程
• http://book.douban.com/subject/1927405/
Inside the Java 2 Virtual Machine
• http://book.douban.com/subject/1788390/
深入理解Java虚拟机
• http://book.douban.com/subject/6522893/
深入嵌入式Java虚拟机
• http://book.douban.com/subject/1103575/
Python源码剖析
• http://book.douban.com/subject/3117898/
Shared Source CLI Essentials
• http://book.douban.com/subject/1484763/
编译原理 技术与工具
• http://book.douban.com/subject/2970069/
深度探索C++对象模型
• http://book.douban.com/subject/1091086/
Oracle JRockit: The Definitive Guide

• http://book.douban.com/subject/4873919/
Java Performance
• http://book.douban.com/subject/5980062/
The Garbage Collection Handbook

• http://book.douban.com/subject/6809987/
The School of Niklaus Wirth
• http://book.douban.com/subject/3152171/
QUESTIONS?
Kris Mok, Software Engineer, Taobao
@rednaxelafx
莫枢 /“撒迦”

为啥别读HotSpot VM的源码(2012-03-03)