编辑推荐
“蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇蟮之穴无可寄托者,用心躁也”。对于技术人员来说,如果长期忽略自身技术的根基而去一昧地追求高层框架技术,这无疑是舍本求末的做法。
相较于C或C++程序员,我发现Java程序员更容易忽视基础技术。JVM的出现,为程序员屏蔽了操作系统与硬件的细节,使得程序员从诸如内存管理这样的繁琐任务中解放出来。但这不并等同于允许Java程序员放弃对基础的重视。我们是否有过这样的经历,在遇到内存故障、丢包、网络协议设计、资源瓶颈、证书、二进制等问题时,往往会觉得比较棘手,在寻求解决思路时更是显得力不从心。这实质上是自身技术遇到了瓶颈难以突破所致。可怕的是,想去深究的时候却无从下手。
我写这本书的初衷是为了唤起Java程序员对于基础技术的重视。事实上,任何平台的程序员都应当了解平台的基本特性、实现机制以及接口,这是提高自身修养的必经之路。对于Java程序员来说,我们需要了解的平台就是JVM。了解JVM的基本实现机制,不仅对于解决实际应用中诸如GC等虚拟机问题时有直接帮助,还有利于我们更好地理解语言本身。
所幸的是,Oracle官方已经将虚拟机项目的源码开放出来,这对于我们来说简直就是福音。本书将以OpenJDK和HotSpot为素材,深入浅出地讲解我们最为熟悉的一款虚拟机产品的实现。除了Java程序员,从事与Java或JVM相关的开发、测试、运维等技术人员也将在本书中获益。
内容简介
《HotSpot实战》深入浅出地讲解了HotSpot虚拟机的工作原理,将隐藏在它内部的本质内容逐一呈现在读者面前,包括OpenJDK与HotSpot项目、编译和调试HotSpot的方法、HotSpot内核结构、Launcher、OOP-Klass对象表示系统、链接、运行时数据区、方法区、常量池和常量池Cache、Perf Data、Crash分析方法、转储分析方法、垃圾收集器的设计演进、CMS和G1收集器、栈、JVM对硬件寄存器的利用、栈顶缓存技术、解释器、字节码表、转发表、Stubs、Code Cache、Code生成器、JIT编译器、C1编译器、编译原理、JVM指令集实现、函数的分发机制、VTABLE和ITABLE、异常表、虚拟机监控工具(如jinfo、jstack、jhat、jmap等)的实现原理和开发方法、Attach机制、基于GUI的JVM分析工具(如MAT、VisualVM)等内容。
除了HotSpot技术,《HotSpot实战》还对方法论进行了探讨。在各个章节的讲解中,都会有一些与系统运行机制相关的实战或练习,供读者练手。通过这些实战练习,不仅有助于读者加深对知识或原理的理解,更为重要的是,它还可以培养读者独立探索的思维方式,这有助于读者把知识融会贯通并灵活应用到实际项目中。
《HotSpot实战》适合于已具有一定Java编程基础的读者,以及在Java或基于JVM的编程语言平台下进行各类软件开发的开发人员、测试人员和运维人员。对于JVM和编程语言爱好者来说,《HotSpot实战》也具有一定的学习参考价值。
作者简介
陈涛,硕士,毕业于中国科技大学。现就职于网易公司旗下的网易宝,从事在线支付系统的设计与开发工作。在从事Java工作之前 ,曾有过Linux内核及驱动开发工作经验。热衷于专研技术,对编程语言和JVM比较感兴趣。工作之余 ,喜欢足球和武侠带来的乐趣。目前正在“专研”的课题是如何做一名称职的奶爸。
目录
- 第1章 初识HotSpot
- 1.1 JDK概述
- 1.1.1 JCP与JSR
- 1.1.2 JDK的发展历程
- 1.1.3 Java 7的语法变化
- 1.2 动手编译虚拟机
- 1.2.1 源代码下载
- 1.2.2 HotSpot源代码结构
- 1.2.3 搭建编译环境
- 1.2.4 编译目标
- 1.2.5 编译过程
- 1.2.6 编译常见问题
- 1.3 实战:在HotSpot内调试HelloWorld
- 1.3.1 认识GDB
- 1.3.2 准备调试脚本
- 1.4 小结
- 第2章 启动
- 2.1 HotSpot内核
- 2.1.1 如何阅读源代码
- 2.1.2 HotSpot内核框架
- 2.1.3 Prims
- 2.1.4 Services
- 2.1.5 Runtime
- 2.2 启动
- 2.2.1 Launcher
- 2.2.2 虚拟机生命周期
- 2.2.3 入口:main函数
- 2.2.4 主线程
- 2.2.5 InitializeJVM函数
- 2.2.6 JNI_CreateJavaVM函数
- 2.2.7 调用Java主方法
- 2.2.8 JVM退出路径
- 2.3 系统初始化
- 2.3.1 配置OS模块
- 2.3.2 配置系统属性
- 2.3.3 加载系统库
- 2.3.4 启动线程
- 2.3.5 vm_init_globals函数:初始化全局数据结构
- 2.3.6 init_globals函数:初始化全局模块
- 2.4 小结
- 第3章 类与对象
- 3.1 对象表示机制
- 3.1.1 OOP-Klass二分模型
- 3.1.2 Oops模块
- 3.1.3 OOP框架与对象访问机制
- 3.1.4 Klass与instanceKlass
- 3.1.5 实战:用HSDB调试HotSpot
- 3.2 类的状态转换
- 3.2.1 入口:Class文件
- 3.2.2 类的状态
- 3.2.3 加载
- 3.2.4 链接
- 3.2.5 初始化
- 3.2.6 实战:类的“族谱”
- 3.2.7 实战:系统字典
- 3.3 创建对象
- 3.3.1 实例对象的创建流程
- 3.3.2 实战:探测JVM内部对象
- 3.4 小结
- 第4章 运行时数据区
- 4.1 堆
- 4.1.1 Java的自动内存管理
- 4.1.2 堆的管理
- 4.2 线程私有区域
- 4.2.1 PC
- 4.2.2 JVM栈
- 4.3 方法区
- 4.3.1 纽带作用
- 4.3.2 常量池
- 4.3.3 常量池缓存:ConstantPoolCache
- 4.3.4 方法的表示:methodOop
- 4.3.5 方法的解析:将符号引用转换成直接引用
- 4.3.6 代码放在哪里:ConstMethodOop
- 4.3.7 实战:探测运行时常量池
- 4.4 性能监控数据区:Perf Data
- 4.4.1 描述这段空间:PerfMemory
- 4.4.2 查看
- 4.4.3 生产
- 4.5 转储
- 4.5.1 用VisualVM进行转储分析
- 4.5.2 JVM Crash
- 4.6 小结
- 第5章 垃圾收集
- 5.1 堆与GC
- 5.1.1 垃圾收集
- 5.1.2 分代收集
- 5.1.3 快速分配
- 5.1.4 栈上分配和逸出分析
- 5.1.5 GC公共模块
- 5.2 垃圾收集器
- 5.2.1 设计演进
- 5.2.2 CMS收集器
- 5.2.3 G1收集器
- 5.3 实战:性能分析方法
- 5.3.1 获取GC日志
- 5.3.2 GC监控信息
- 5.3.3 内存分析工具
- 5.3.4 选择合适的收集器与GC性能评估
- 5.3.5 不要忽略JVM Crash日志
- 5.4 小结
- 第6章 栈
- 6.1 硬件背景:了解真实机器
- 6.1.1 程序是如何运行的
- 6.1.2 x86与栈帧
- 6.1.3 ARM对Java硬件级加速:Jazelle技术
- 6.2 Java栈
- 6.2.1 寄存器式指令集与栈式指令集
- 6.2.2 HotSpot中的栈
- 6.2.3 栈帧
- 6.2.4 充分利用寄存器资源
- 6.2.5 虚拟机如何调用Java函数
- 6.2.6 优化:栈顶缓存
- 6.2.7 实战:操作数栈
- 6.3 小结
- 第7章 解释器和即时编译器
- 7.1 概述
- 7.2 解释器如何工作
- 7.2.1 Interpreter模块
- 7.2.2 Code模块
- 7.2.3 字节码表
- 7.2.4 Code Cache
- 7.2.5 InterpreterCodelet与Stub队列
- 7.2.6 Code生成器
- 7.2.7 模板表与转发表
- 7.2.8 实战:InterpreterCodelet
- 7.3 即时编译器
- 7.3.1 概述
- 7.3.2 编译器模块
- 7.3.3 编译器的基本结构
- 7.3.4 实战:编译原理实践,了解编译中间环节
- 7.4 小结
- 第8章 指令集
- 8.1 再说栈式指令集
- 8.2 数据传送
- 8.2.1 局部变量、常量池和操作数栈之间的数据传送
- 8.2.2 数据传送指令
- 8.2.3 实战:数组的越界检查
- 8.3 类型转换
- 8.4 对象的创建和操作
- 8.5 程序流程控制
- 8.5.1 控制转移指令
- 8.5.2 条件转移
- 8.5.3 无条件转移
- 8.5.4 复合条件转移
- 8.5.5 实战:switch语句如何使用String
- 8.6 运算
- 8.6.1 加法:iadd
- 8.6.2 取负:ineg
- 8.7 函数的调用和返回
- 8.7.1 Java函数分发机制:VTABLE与ITABLE
- 8.7.2 invoke系列指令
- 8.7.3 动态分发:覆盖
- 8.7.4 静态分发:重载
- 8.8 异常
- 8.8.1 异常表
- 8.8.2 创建异常
- 8.8.3 try-catch
- 8.8.4 finally
- 8.9 小结
- 第9章 虚拟机监控工具
- 9.1 Attach机制
- 9.1.1 AttachProvider与VirtualMachine
- 9.1.2 命令的下发:execute()
- 9.1.3 命令的执行:Attach Listener守护线程
- 9.2 查看JVM进程
- 9.2.1 用jps查看Java进程
- 9.2.2 实战:定制jps,允许查看库路径
- 9.3 查看和配置JVM
- 9.3.1 用jinfo查看JVM参数配置
- 9.3.2 实战:扩展flags选项,允许查看命令行参数
- 9.4 堆内存转储工具
- 9.4.1 Heap Dump
- 9.4.2 原理
- 9.5 堆转储分析
- 9.5.1 Heap Dump分析工具:jhat
- 9.5.2 实战:MAT分析过程
- 9.6 线程转储分析
- 9.6.1 jstack
- 9.6.2 实战:如何分析资源等待
- 9.7 小结