ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
Java是目前用户最多、使用范围最广的软件开发技术,Java的技术体系主要由支撑Java程序运行的虚拟机、提供各开发领域接口支持的Java类库、Java编程语言及许许多多的第三方Java框架(如Spring、MyBatis等)构成。在国内,有关Java类库API、Java语言语法及第三方框架的技术资料和书籍非常丰富,相比而言,有关Java虚拟机的资料却显得异常贫乏。 这种状况很大程度上是由Java开发技术本身的一个重要优点导致的:在虚拟机层面隐藏了底层技术的复杂性以及机器与操作系统的差异性。运行程序的物理机千差万别,而Java虚拟机则在千差万别的物理机上面建立了统一的运行平台,实现了在任意一台Java虚拟机上编译的程序,都能在任何其他Java虚拟机上正常运行。这一极大的优势使得Java应用的开发比传统C/C++应用的开发更高效快捷,程序员可以把主要精力放在具体业务逻辑,而不是放在保障物理硬件的兼容性上。通常情况下,一个程序员只要了解了必要的Java类库API、Java语法,学习适当的第三方开发框架,就已经基本满足日常开发的需要了。虚拟机会在用户不知不觉中完成对硬件平台的兼容及对内存等资源的管理工作。因此,了解虚拟机的运作并不是普通开发人员必备的,或者说首要学习的知识。 然而,凡事都具备两面性。随着Java技术的不断发展,它已被应用于越来越多的领域之中。其中一些领域,如互联网、能源、金融、通信等,对程序的性能、稳定性和扩展性方面会有极高的要求。一段程序很可能在10个人同时使用时完全正常,但是在10000个人同时使用时就会缓慢、死锁甚至崩溃。毫无疑问,要满足10000个人同时使用,需要更高性能的物理硬件,但是在绝大多数情况下,提升硬件性能无法等比例提升程序的运行性能和并发能力,甚至有可能对程序运行状况没有任何改善。这里面有Java虚拟机的原因:为了达到“所有硬件提供一致的虚拟平台”的目的,牺牲了一些硬件相关的性能特性。更重要的是人为原因:如果开发人员不了解虚拟机诸多技术特性的运行原理,就无法写出最适合虚拟机运行和自优化的代码。 其实,目前商用的高性能Java虚拟机都提供了相当多的优化参数和调节手段,用于满足应用程序在实际生产环境中对性能和稳定性的要求。如果只是为了入门学习,让程序在自己的机器上正常工作,那么这些特性可以说是可有可无的;但是,如果用于生产开发,尤其是大规模的、企业级的生产开发,就迫切需要开发人员中至少有一部分人对虚拟机的特性及调节方法具有很清晰的认识。所以在Java开发体系中,对架构师、系统调优师、高级程序员等角色的需求一直都非常大。学习虚拟机中各种自动运作特性的原理也成为Java程序员成长路上最终必然会接触到的一课。通过本书,读者可以以一个相对轻松的方式学到虚拟机的运作原理。 本书面向的读者 (1)使用Java技术体系的中、高级开发人员 Java虚拟机作为中、高级开发人员修炼的必要知识,有着较高的学习门槛,本书可作为学习虚拟机的教材。 (2)系统调优师 系统调优师是最近几年才兴起并迅速流行起来的职业,本书中的大量案例、代码和调优实战将会对系统调优师的日常工作有直接的参考作用。 (3)系统架构师 保障系统的性能、并发和伸缩等能力是系统架构师的主要职责之一,而这部分与虚拟机的运作密不可分,本书可以作为他们制定应用系统底层框架的参考资料。 如何阅读本书 本书一共分为五个部分:走近Java、自动内存管理、虚拟机执行子系统、程序编译与代码优化、高效并发。各个部分之间基本上是互相独立的,没有必然的前后依赖关系,读者可以从任何一个感兴趣的专题开始阅读,但是每个部分各个章节间则有先后顺序。 这里并没有假定所有读者都在Java领域具备特别专业的技术水平,因此会在保证逻辑完整、描述准确的前提下,尽量用通俗的语言和案例去讲述虚拟机中与开发关系最为密切的内容。但是,本书毕竟是在探讨虚拟机的工作原理,不可避免地需要读者有一定的技术基础,而且本书的读者定位是中、高级程序员群体,对于一些常用的开发框架、Java类库API和Java语法等基础知识点,将假设读者已有所了解。 本书介绍的Java虚拟机并不局限于某一个特定发行商或者某一款特定虚拟机,只是由于OracleJDK/OpenJDK在市场占有率上的绝对优势,其中的HotSpot虚拟机不可避免地成为本书主要分析、讲解的对象,书中在涉及Java虚拟机自身实现相关的内容时,大多将以HotSpot虚拟机为目标对象来进行讲解。但撰写本书的意图并不是去做HotSpot的源码导读或者解析,书中所讲述的内容多为Java虚拟机的通用原理,即使读者使用了HotSpot之外的其他Java虚拟机实现,也会有所收获。 最后,非常希望读者能跟随本书的讲解,把与实践相关的内容亲自验证一遍,其中用到的代码清单可以从华章图书的网站(http://www.hzbook.com/)上下载。 语言约定 开始阅读本书之前,在语言和技术上先与读者建立如下约定: ·JDK从1.5版本开始,其官方的正式文档与宣传材料中的发行版本号启用了JDK 5、6、7……的新命名方式;从2018年3月发布的JDK 10起,JDK的开发版本号(如java-version)也放弃了以前1.x的命名形式,改为按发布的日期时间命名。本书为了行文一致,所有场合统一采用发行版本号来指代所述的JDK版本。 ·由于版面原因,本书中的许多示例代码都没有遵循最优的程序编写风格,如使用的流没有关闭流、直接使用System.out输出日志等,请读者在阅读时注意这一点。 ·本书讲解中涉及JDK 7以前HotSpot虚拟机、JRockit虚拟机、WebLogic服务器等产品的所有者时,仍然会使用BEA和Sun公司的名称,而不是Oracle。实际上BEA和Sun分别于2008年和2010年被Oracle公司收购,现在已经不存在这两个商标了,但是它们毫无疑问都是在Java领域中做出过卓越贡献的、值得程序员们纪念的先驱企业。 ·本书第3版撰写于2019年中期,此时JDK 13已有了技术预览版(Early Access),但尚未正式发布。本书中所有的讲解、讨论都是基于这个时间点的Java技术的,但并不针对特定的JDK版本。如涉及JDK新版本中加入的功能,或在不同版本中有所变化的特性,笔者都会明确指出JDK的版本号,或专门阐述各个版本间的差异。 内容特色与更新 本书的第2版成文于2011至2012年间,出版于2013年,撰写时是基于早期版本的JDK 7,彼时正值Oracle全面替代Sun公司领导Java技术发展的起点。经过将近十年的时间,今天JDK版本已经发展到了JDK 12及预览版的JDK 13,整个Java技术体系一改Sun时代的迟缓作风,出现了许多激烈的变革,也涌现了不少令人欣喜的新变化、新风潮。我在撰写本书第3版时,期望能把这些新的变化融合到已有的知识框架中,修改第2版中读者反馈的问题,提升叙述的准确性与可读性,这些期望中的更新使得本书字数从原有的24万增加到35万。因此,在前言部分,笔者针对每章列举出主要更新的内容,以便阅读过第2版的读者可以快速定位,获取到新的知识。当然,如果你尚有余暇,不妨从头阅读一次本书,相信会有与阅读第2版时不一样的体验和收获。 第一部分 走近Java 本书的第一部分为后文的研究和讲解建立了良好的基础。虽然了解Java技术的来龙去脉,以及编译自己的OpenJDK对于读者理解Java虚拟机并不是必须的,但是这些准备过程可以为走近Java技术和Java虚拟机提供良好的引导。第一部分只有第1章: 第1章 介绍了Java技术体系过去、现在的情况以及未来的发展趋势,并在实践中介绍了如何自己编译一个OpenJDK 12。 [插图]第3版更新:续写了Java技术发展史,这几年Java世界着实发生了很多值得记录的大事件;完全重写了第2版对未来Java的展望预测,当时畅想的Java新发展新变化全部如约而至,是时候把聚光灯交给下一个十年的Java了;OpenJDK开发、编译也发生过不小的变动,本次更新将OpenJDK编译的版本提升到12。 第二部分 自动内存管理 因为程序员把控制内存的权力交给了Java虚拟机,所以可以在编码的时候享受自动内存管理的诸多优势,不过也正因为这个原因,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那排查错误将会成为一项异常艰难的工作。第二部分包括第2~5章: 第2章 介绍了虚拟机中内存是如何划分的,哪部分区域、什么样的代码和操作可能导致内存溢出异常,并讲解了各个区域出现内存溢出异常的常见原因。 [插图]第3版更新:Java运行期数据区域是虚拟机的基础结构,尽管JDK版本在快速发展,这块内容仍然保持了相对的稳定,主要的变化是JDK 8时期的永久代的落幕和元空间的登场;除此以外,本章着重修正了第2版中对Java虚拟机栈描述的含糊与偏差之处,还更新了部分测试代码,避免因JDK版本更迭导致与书中不一样的结果。 第3章 介绍了垃圾收集的算法和HotSpot虚拟机中提供的几款垃圾收集器的特点及运作原理。通过代码实例验证了Java虚拟机中自动内存分配及回收的主要规则。 [插图]第3版更新:由于撰写第2版时JDK 7刚刚发布,G1收集器尚无实践数据可查,书中对此讲述得比较含糊,本次更新完全重写了这部分内容,并重点增加了JDK 11、12中新出现的ZGC和Shenandoah两款低延迟全并发收集器的详细原理解析,这是垃圾收集器未来的发展方向。对其他与收集器相关的更新,如统一收集器接口、Epsilon等也都做了对应介绍。此外,针对HotSpot中收集器实现的几个关键技术点,如解决跨代引用的记忆集与卡表、解决并发标记的增量更新和原始快照算法,还有内存读、写屏障等技术都增加了专门的小节来进行介绍,以便帮读者在后续深入阅读HotSpot设计与源码时打下良好的理论基础。 第4章 介绍了随JDK发布的基础命令行工具与可视化的故障处理工具的使用方法。 [插图]第3版更新:Java虚拟机的各种监控、管理等辅助工具的功能日益强大,几乎每个版本在这些工具的数量、功能上都会或多或少有所变化,除了将第2版涉及的工具的变化依照JDK版本进行升级外,本章还新增了对JDK 9中加入的JHSDB的使用讲解,并增加了对JFR和JMC的工作原理和使用方法的介绍,以及对部分JDK外部的工具(如JIT Watch)的简要介绍。 第5章 分享了几个比较有代表性的实际案例,还准备了一个所有开发人员都能“亲身实战”的练习,希望读者能通过实践来获得故障处理和调优的经验。 [插图]第3版更新:对案例部分进行了更新和增补,着重补充了与前3章新增内容相对应的问题处理案例。不过对实战部分,软件版本的落后并未影响笔者要表达的内容,原有的实战目前仍具有相同的实战价值,在第3版里笔者也并未刻意将Eclipse和HotSpot升级后重写一次。 第三部分 虚拟机执行子系统 执行子系统是虚拟机中必不可少的组成部分,了解了虚拟机如何执行程序,才能更好地理解怎样才能写出优秀的代码。第三部分包括第6~9章: 第6章 讲解了Class文件结构中的各个组成部分,以及每个部分的定义、数据结构和使用方法,以实战的方式演示了Class的数据是如何存储和访问的。 [插图]第3版更新:笔者认为本章内容更适合以“技术手册”的形式存在,即适合查阅多于适合阅读,但因为Class文件格式是虚拟机的基础知识,所以尽管枯燥却无法回避。本次更新将Class文件格式的版本跟进到了JDK 12,《Java虚拟机规范》对Class文件格式进行的增强也会在本章中反映,内容相对琐碎。例如,为了实现JDK 9的Java模块化系统,属性表中新增了Module、ModulePackages、ModuleMain-Class三项新属性,常量池中加入了CONSTANT_Module_info和CONSTANT_Package_info两个常量。为了实现JDK 11新增的嵌套内(Java中的内部类)访问控制的API,属性表中又增加了NestHost和NestMembers两项属性。为进一步加强动态语言支持,CONSTANT_Dynamic_info常量也在JDK 11期间加入常量池…… 第7章 介绍了类加载过程的“加载”“验证”“准备”“解析”和“初始化”五个阶段中虚拟机分别进行了哪些动作,还介绍了类加载器的工作原理及其对虚拟机的意义。 [插图]第3版更新:随着Class文件格式的发展,类加载的各个过程都发生了一些细节性变动,本章将会按照JDK 12版本的《Java虚拟机规范》的标准来同步更新这些内容。此外,在JDK 9时引入了Java模块化系统,这是近年来Java技术的一次重要升级,也是对类加载部分影响巨大的一项变革,在本章将加入专门的小节对其进行讲述。 第8章 分析了虚拟机在执行代码时,如何找到正确的方法、如何执行方法内的字节码,以及执行代码时涉及的内存结构。 [插图]第3版更新:本章讲述的是Java虚拟机执行子系统的概念模型,这部分属于相对稳定的内容,变化不大,本次主要更新了Java虚拟机对动态类型语言支持的增强。 第9章 通过几个类加载及执行子系统的案例,介绍了使用类加载器和处理字节码的一些值得欣赏和借鉴的思路,并通过一个实战练习加深读者对前面理论知识的理解。 [插图]第3版更新:原有章节所涉及的案例中,程序、类库、工具的版本已经较为陈旧,本次更新对这些案例涉及的版本进行了升级,以反映在模块化、Lambda表达式、动态语言等新技术出现后它们的相应变化。 第四部分 程序编译与代码优化 Java程序从源码编译成字节码,再从字节码编译成本地机器码的这两个过程,从整体来看其实等同于一个传统编译器所执行的编译前端、后端过程。第四部分包括第10~11章: 第10章 分析了Java语言中泛型、主动装箱拆箱、条件编译等多种语法糖的前因后果,并实战练习了如何使用插入式注解处理器来完成一个检查程序命名规范的编译器插件。 [插图]第3版更新:对第2版介绍泛型的小节进行了全文重写,描述了不同语言里泛型实现的方式、Java泛型出现的历史背景和使用类型擦除来实现泛型所带来的一些限制,并介绍了未来可能会在Java中出现的值类型等内容。 第11章 讲解了虚拟机的热点探测方法、HotSpot的即时编译器、编译触发条件,以及如何从虚拟机外部观察和分析即时编译的数据和结果,还选择了几种常见的编译期优化技术进行讲解。 [插图]第3版更新:专门增加了介绍提前编译器的章节;由于HotSpot中新的Graal编译器的加入,书中除了同步增加Graal编译器、JVMCI接口等内容,为了使读者可以在HotSpot编译器上进行实战练习,在本书第3版中还新增了许多编译器的实战内容。 第五部分 高效并发 Java语言和虚拟机提供了原生的、完善的多线程支持,使得它天生就适合开发多线程并发的应用程序。不过我们不能期望系统来完成所有与并发相关的处理,了解并发的内幕也是成为一位高级程序员不可缺少的课程。第五部分包括第12~13章: 第12章 讲解了虚拟机Java内存模型的结构及操作,以及原子性、可见性和有序性在Java内存模型中的体现;介绍了先行发生原则的规则及使用,以及线程在Java语言之中是如何实现的;还提前介绍了目前仍然在实验室状态的Java协程的相关内容。 第3版更新:重写了原有的对Java内存模型部分过时和过于晦涩的描述,增加了面向Java未来基于协程的新并发模型的介绍。 第13章 介绍了线程安全所涉及的概念和分类、同步实现的方式及虚拟机的底层运作原理,并且介绍了虚拟机实现高效并发所做的一系列锁优化措施。 [插图]第3版更新:本章主体内容并没有过多变化,但对不少细节进行了修饰,对一些读者疑问较多的地方进行了补充讲解。 * [ ] 参考资料 本书名为“深入理解Java虚拟机”,但要想真的深入理解虚拟机,仅凭一本书肯定是远远不够的,读者可以通过以下方式查找到更多关于Java虚拟机方面的资料。笔者在写作此书的时候,也从下面这些参考资料中得到过很大的帮助。 * [ ] 1、书籍 * 《Java虚拟机规范》 要学习虚拟机,《Java虚拟机规范》无论如何都是必须读的。这本书的概念和细节描述与Sun的早期虚拟机(Sun Classic虚拟机)高度吻合,随着技术的发展,高性能虚拟机真正的细节实现方式已经渐渐与虚拟机规范所描述的方式差距越来越大,如果只能选择一本参考书来了解Java虚拟机,那必然是这本书。 * 《Java语言规范》 虽然Java虚拟机并不是Java语言专有的,但是了解Java语言的各种细节规定对虚拟机的行为也是很有帮助的,它与《Java虚拟机规范》一样都是Oracle官方直接出版的书籍,而且这本书还是由Java之父James Gosling亲自执笔撰写。 * 《垃圾回收算法手册:自动内存管理的艺术》 2016年3月由机械工业出版社引进翻译,这是一本真正的教科书式的学术著作,是垃圾收集技术领域中的唯一必读的书籍。该书从硬件与软件的发展给垃圾回收所带来的新挑战出发,探讨了这些挑战给高性能垃圾回收器的设计者与实现者所带来的影响,涵盖了并行垃圾回收、增量式垃圾回收、并发垃圾回收以及实时垃圾回收,描述各种算法与概念。唯一缺点是由于过于专业,所以显得比较晦涩,不适合作为入门书籍使用。 * 《Virtual Machines:Versatile Platforms for Systems and Processes》 这是一本虚拟化技术的百科全书,帮助读者理解“虚拟机”一词到底指代什么,有什么不同类型,大概有哪些实现方法等。此书并不直接针对Java虚拟机,出版于2005年,而且国内并没有中文版,但即使有这些因素限制,仍然推荐读者阅读此书以建立对虚拟机的全局性观念。 * 《Java性能优化权威指南》 此书是“The Java”系列(该系列中最出名的《Effective Java》许多人都读过)图书中最新的一本,但也有一定的历史了。2011年10月出版,2014年3月由人民邮电出版社引进翻译。这本书并非全部都围绕Java虚拟机展开(只有第3、4、7章直接与Java虚拟机相关),而是从操作系统到基于Java的上层程序性能度量和调优进行全面介绍。其中涉及Java虚拟机的内容具备一定深度和很好的可实践性。 * [ ] 2、网站资源 * 高级语言虚拟机圈子:http://hllvm.group.iteye.com/。 里面有一些关于虚拟机的讨论,并不只限于Java虚拟机,包括了所有针对高级语言虚拟机(High-Level Language Virtual Machine)的讨论,不过该网站针对Java虚拟机的讨论还是绝对的主流。圈主RednaxelaFX(莫枢)的博客(http://rednaxelafx.iteye.com/) 是另外一个非常有价值的虚拟机及编译原理等资料的分享园地。 * HotSpot Internals:https://wiki.openjdk.java.net/display/HotSpot/Main。 这是一个关于OpenJDK的Wiki网站,许多文章都由JDK的开发团队编写,更新很慢,但是有很大的参考价值。 * The HotSpot Group:http://openjdk.java.net/groups/hotspot/。 HotSpot组群,里面有关于虚拟机开发、编译器、垃圾收集和运行时四个邮件组,包含了关于HotSpot虚拟机最新的讨论。 * [ ] 联系作者 在本书交稿的时候,我并没有想象中那样兴奋或放松,写作之时那种“战战兢兢、如履薄冰”的感觉依然萦绕在心头。在每一章、每一节落笔之时,我都在考虑如何才能把各个知识点更有条理地讲述出来,都在担心会不会由于自己理解有偏差而误导了大家。囿于我的写作水平和写作时间,书中难免存在不妥之处,所以大家如有任何意见或建议,欢迎到本工程地址https://github.com/fenixsoft/jvm_book 与我联系。相信写书与写程序一样,作品一定都是不完美的,因为不完美,我们才有不断追求完美的动力。