Java是目前用户最多、使用范围最广的软件开发技术之一。Java的技术体系主要由支撑Java程序运行的虚拟机、提供各开发领域接口支持的Java API、Java编程语言及许多第三方Java框架(如Spring、Struts等)构成。在国内,有关Java API、Java语言语法及第三方框架的技术资料和书籍非常丰富,相比之下,有关Java虚拟机的资料却显得异常贫乏。
这种状况在很大程度上是由Java开发技术本身的一个重要优点导致的:在虚拟机层面隐藏了底层技术的复杂性以及机器与操作系统的差异性。运行程序的物理机器的情况千差万别,而Java虚拟机则在千差万别的物理机上建立了统一的运行平台,实现了在任意一台虚拟机上编译的程序都能在任何一台虚拟机上正常运行。这一极大优势使得Java应用的开发比传统C/C++应用的开发更高效和快捷,程序员可以把主要精力集中在具体业务逻辑上,而不是物理硬件的兼容性上。在一般情况下,一个程序员只要了解了必要的Java API、Java语法,以及学习适当的第三方开发框架,就已经基本能满足日常开发的需要了,虚拟机会在用户不知不觉中完成对硬件平台的兼容及对内存等资源的管理工作。因此,了解虚拟机的运作并不是一般开发人员必须掌握的知识。
然而,凡事都具备两面性。随着Java技术的不断发展,它被应用于越来越多的领域之中。其中一些领域,如电力、金融、通信等,对程序的性能、稳定性和可扩展性方面都有极高的要求。程序很可能在10个人同时使用时完全正常,但是在10?000个人同时使用时就会缓慢、死锁,甚至崩溃。毫无疑问,要满足10?000个人同时使用需要更高性能的物理硬件,但是在绝大多数情况下,提升硬件效能无法等比例地提升程序的运作性能和并发能力,甚至可能对程序运作状况完全没有任何改善。这里面有Java虚拟机的原因:为了达到给所有硬件提供一致的虚拟平台的目的,牺牲了一些与硬件相关的性能特性。更重要的是人为原因:如果开发人员不了解虚拟机一些技术特性的运行原理,就无法写出最适合虚拟机运行和自优化的代码。
其实,目前商用的高性能Java虚拟机都提供了相当多的优化特性和调节手段,用于满足应用程序在实际生产环境中对性能和稳定性的要求。如果只是为了入门学习,让程序在自己的机器上正常运行,那么这些特性可以说是可有可无的;如果用于生产开发,尤其是企业级生产开发,就迫切需要开发人员中至少有一部分人对虚拟机的特性及调节方法具有很清晰的认识,所以在Java开发体系中,对架构师、系统调优师、高级程序员等角色的需求一直都非常大。学习虚拟机中各种自动运作特性的原理也成为了Java程序员成长道路上必然会接触到的一课。本书可以使读者以一种相对轻松的方式学习虚拟机的运作原理,对Java程序员的成长也有较大的帮助。
第2版与第1版的区别
JDK 1.7在2011年7月28日正式发布,相对于2006年发布的JDK 1.6,新版的JDK有了许多新的特性和改进。本书的第2版也相应地进行了修改和升级,把讲解的技术平台从JDK 1.6提升至JDK 1.7。例如,增加了对JDK 1.7中最新的G1收集器,以及JDK 1.7中JSR-292 InvokeDynamic(对非Java语言的调用支持)的分析讲解等内容。
在第1版出版后,笔者收到了许多热心读者的反馈意见,部分读者提出OpenJDK开源已久,第1版却很少有直接分析OpenJDK源码的内容,有点“视宝山而不见”的感觉。因此,在本书第2版中,笔者特别加强了对这部分内容的讲解,其中在第1章中就介绍了如何分析、调试OpenJDK源码等。在本书后续章节中,不少关于功能点的讲解都直接使用OpenJDK中的HotSpot源码或者JIT编译器生成的本地代码作为论据。
如何把Java虚拟机原理中许多理论性很强的知识、特性应用于实践开发,是本书贯穿始终的主旨。由于笔者希望在本书第2版中进一步加强知识的实践性,因此增加了许多对处理JVM常见问题技能的讲解,包括如何分析GC日志、如何分析JIT编译器代码优化过程和生成代码等。并且,在第1版的基础上,第2版中进一步增加了若干处理JVM问题的实践案例供读者参考。
另外,本书第2版还修正了第1版中多处错误的、有歧义的和不完整的描述。有关勘误信息,可以参考第1版的勘误页面(http://icyfenix.iteye.com/blog/1119214)。
本书面向的读者
(1)使用Java技术体系的中、高级开发人员
Java虚拟机作为中、高级开发人员必须修炼的知识,有着较高的学习门槛,本书可作为学习虚拟机的优秀教材。
(2)系统调优师
系统调优师是近几年才兴起的职业,本书中的大量案例、代码和调优实战将会对系统调优师的日常工作有直接的帮助。
(3)系统架构师
保障系统的性能、并发和伸缩等能力是系统架构师的主要职责之一,而这部分与虚拟机的运作密不可分,本书可以作为他们制定应用系统底层框架的参考资料。
如何阅读本书
本书一共分为五个部分:走近Java、自动内存管理机制、虚拟机执行子系统、程序编译与代码优化、高效并发。各部分基本上是互相独立的,没有必然的前后依赖关系,读者可以从任何一个感兴趣的专题开始阅读,但是每个部分中的各个章节间有先后顺序。
本书并没有假设读者在Java领域具备很专业的技术水平,因此在保证逻辑准确的前提下,尽量用通俗的语言和案例讲述虚拟机中与开发的关系最为密切的内容。当然,学习虚拟机技术本身就需要读者有一定的基础,且本书的读者定位是中、高级程序员,因此本书假设读者自己了解一些常用的开发框架、Java API和Java语法等基础知识。
笔者希望读者在阅读本书的同时,把本书中的实践内容亲自验证一遍,其中用到的代码清单可以从华章网站(http://www.hzbook.com)下载。
语言约定
本书在语言和技术上有如下约定:
?本书中提到HotSpot、JRockit虚拟机、WebLogic服务器等产品的所有者时,仍然使用Sun和BEA公司的名称,实际上,BEA和Sun分别于2008年和2009年被Oracle公司收购,现在已经不存在这两个商标了,但毫无疑问的是,它们都是在Java领域中做出过卓越贡献的、值得程序员纪念的公司。
?JDK从1.5版本开始,在官方的正式文档与宣传资料中已经不再使用类似“JDK 1.5”的名称,只有程序员内部使用的开发版本号(Developer Version,例如java-version的输出)才继续沿用1.5、1.6和1.7的版本号,而公开版本号(Product Version)则改为JDK 5、JDK 6和JDK 7的命名方式,为了行文一致,本书所有场合统一采用开发版本号的命名方式。
?由于版面关系,本书中的许多示例代码都没有遵循最优的代码编写风格,如使用的流没有关闭流等,请读者在阅读时注意这一点。
?如果没有特殊说明,本书中所有讨论都是以Sun JDK 1.7为技术平台的。不过如果有某个特性在各个版本间的变化较大,一般都会说明它在各个版本间的差异。
内容特色
第一部分 走近Java
本书的第一部分为后文的讲解建立了良好的基础。尽管了解Java技术的来龙去脉,以及编译自己的OpenJDK对于读者理解Java虚拟机并不是必需的,但是这些准备过程可以为走近Java技术和Java虚拟机提供很好的引导。第一部分只有第1章:
第1章 介绍了Java技术体系的过去、现在和未来的一些发展趋势,并介绍了如何独立地编译一个OpenJDK 7。
第二部分 自动内存管理机制
因为程序员把内存控制的权力交给了Java虚拟机,所以可以在编码的时候享受自动内存管理的诸多优势,不过也正是这个原因,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会成为一项异常艰难的工作。第二部分包括第2~5章:
第2章 讲解了虚拟机中内存是如何划分的,以及哪部分区域、什么样的代码和操作可能导致内存溢出异常,并讲解了各个区域出现内存溢出异常的常见原因。
第3章 分析了垃圾收集的算法和JDK 1.7中提供的几款垃圾收集器的特点及运作原理。通过代码实例验证了Java虚拟机中自动内存分配及回收的主要规则。
第4章 介绍了随JDK发布的6个命令行工具与两个可视化的故障处理工具的使用方法。
第5章 与读者分享了几个比较有代表性的实际案例,还准备了一个所有开发人员都能“亲身实战”的练习,读者可通过实践来获得故障处理和调优的经验。
第三部分 虚拟机执行子系统
执行子系统是虚拟机中必不可少的组成部分,了解了虚拟机如何执行程序,才能写出更优秀的代码。第三部分包括第6~9章:
第6章 讲解了Class文件结构中的各个组成部分,以及每个部分的定义、数据结构和使用方法,以实战的方式演示了Class文件的数据是如何存储和访问的。
第7章 介绍了类加载过程的“加载”、“验证”、“准备”、“解析”和“初始化”5个阶段中虚拟机分别执行了哪些动作,还介绍了类加载器的工作原理及其对虚拟机的意义。
第8章 分析了虚拟机在执行代码时如何找到正确的方法,如何执行方法内的字节码,以及执行代码时涉及的内存结构。
第9章 通过4个类加载及执行子系统的案例,分享了使用类加载器和处理字节码的一些值得欣赏和借鉴的思路,并通过一个实战练习来加深对前面理论知识的理解。
第四部分 程序编译与代码优化
Java程序从源码编译成字节码和从字节码编译成本地机器码的这两个过程,合并起来其实就等同于一个传统编译器所执行的编译过程。第四部分包括第10~11章:
第10章 分析了Java语言中泛型、主动装箱和拆箱、条件编译等多种语法糖的前因后果,并通过实战演示了如何使用插入式注解处理器来实现一个检查程序命名规范的编译器插件。
第11章 讲解了虚拟机的热点探测方法、HotSpot的即时编译器、编译触发条件,以及如何从虚拟机外部观察和分析JIT编译的数据和结果,此外,还讲解了几种常见的编译优化技术。
第五部分 高效并发
Java语言和虚拟机提供了原生的、完善的多线程支持,这使得它天生就适合开发多线程并发的应用程序。不过我们不能期望系统来完成所有并发相关的处理,了解并发的内幕也是成为一个高级程序员不可缺少的课程。第五部分包括第12~13章:
第12章 讲解了虚拟机Java内存模型的结构及操作,以及原子性、可见性和有序性在Java内存模型中的体现,介绍了先行发生原则的规则及使用,还了解了线程在Java语言中是如何实现的。
第13章 介绍了线程安全涉及的概念和分类、同步实现的方式及虚拟机的底层运作原理,并且介绍了虚拟机实现高效并发所采取的一系列锁优化措施。
参考资料
本书名为“深入理解Java虚拟机”,但要想深入理解虚拟机,仅凭一本书肯定是远远不够的,读者可以通过以下信息找到更多关于Java虚拟机方面的资料。我在写作此书的时候,也从下面这些参考资料中获得了很大的帮助。
(1)书籍
?《The Java Virtual Machine Specification,Java SE 7 Edition》
要学习虚拟机,无论如何都必须掌握“Java虚拟机规范”。这本书的概念和细节描述与Sun的早期虚拟机(Sun Classic VM)高度吻合,不过,随着技术的发展,高性能虚拟机真正的细节实现方式已经渐渐与虚拟机规范所描述的差距越来越大,如果只能选择一本参考书来了解虚拟机,那我推荐这本书。此书的Java SE 7版在2011年7月出版发行,这是自1999年发布的《Java虚拟机规范(第2版)》以来的第一次版本更新。笔者对Java SE 7版的全文进行了翻译,并与原书一样在网上免费发布了全文PDF。
?《The Java Language Specification,Java SE 7 Edition》
虽然虚拟机并不是Java语言专有的,但是了解Java语言的各种细节规定对理解虚拟机的行为也是很有帮助的,它与上一本《Java虚拟机规范》都是Sun官方出品的书籍,而且这本书还是由Java之父James Gosling亲自执笔撰写的。这本书也与《Java虚拟机规范》一样,可以在官方网站完全免费下载到全文PDF,但暂时没有中文译本,《Java语言规范(第3版)》于2005年7月由机械工业出版社引进出版。
?《Oracle JRockit The Definitive Guide》
《Oracle JRockit权威指南》,2010年7月出版,国内也没有(可能是尚未)引进这本书,它是由JRockit的两位资深开发人员(其中一位还是JRockit Mission Control团队的TeamLeader)撰写的JRockit虚拟机高级使用指南。虽然JRockit的用户量可能不如HotSpot多,但也是目前最流行的三大商业虚拟机之一,并且不同虚拟机中的很多实现思路都是可以对比参照的。这本书是了解现代高性能虚拟机很好的参考资料。
?《Inside the Java 2 Virtual Machine,Second Edition》
《深入Java虚拟机(第2版)》,2000年1月出版,2003年由机械工业出版社出版其中文译本。在相当长的时间里,这本书是唯一的一本关于Java虚拟机的中文图书。
?《Java Performance》
《Java Performance》是“The Java”系列(许多人都读过该系列中最出名的《Effective Java》)图书中最新的一本,2011年10月出版,暂时没有中文版。这本书并非全部都围绕Java虚拟机(只有第3、4、7章直接与Java虚拟机相关),而是从操作系统到基于Java的上层程序性能度量和调优的全面介绍,其中涉及Java虚拟机的内容具备一定的深度和可实践性。
(2)网站资源
?高级语言虚拟机圈子:http://hllvm.group.iteye.com/
里面有一些国内关于虚拟机的讨论,并不只限于JVM,而是涉及对所有的高级语言虚拟机(High-Level Language Virtual Machine)的讨论,但该网站建立在ITEye上,自然还是以讨论Java虚拟机为主。圈主RednaxelaFX(莫枢)的博客(http://rednaxelafx.iteye.com/)是另外一个非常有价值的虚拟机及编译原理等资料的分享园地。
?HotSpot Internals:https://wikis.oracle.com/display/HotSpotInternals/Home
一个关于OpenJDK的Wiki网站,许多文章都由JDK的开发团队编写,更新较慢,但是仍然有很高的参考价值。
?The HotSpot Group:http://openjdk.java.net/groups/hotspot/
HotSpot组群,包含虚拟机开发、编译器、垃圾收集和运行时4个邮件组,其中有关于HotSpot虚拟机的最新讨论。
勘误和支持
在本书交稿的时候,我并不像想象中的那样兴奋或放松,写作之时那种“战战兢兢、如履薄冰”的感觉依然萦绕在心头。在每一章、每一节落笔之时,我都在考虑如何才能把各个知识点更有条理地讲述出来,同时也在担心会不会由于自己理解有偏差而误导了读者。由于写作水平和写作时间所限,书中难免存在不妥之处,所以特地开通了一个读者邮箱(understandingjvm@gmail.com)与大家交流,大家如有任何意见或建议欢迎与我联系。相信写书与写程序一样,作品一定都是不完美的,因为不完美,我们才有不断追求完美的动力。
本书第2版的勘误,将会在作者的博客(http://icyfenix.iteye.com/)中发布。欢迎读者在博客上留言。
致谢
首先要感谢我的家人,在本书写作期间全靠他们对我的悉心照顾,才让我能够全身心地投入到写作之中,而无后顾之忧。
同时要感谢我的工作单位远光软件,公司为我提供了宝贵的工作、学习和实践的环境,书中的许多知识点都来自于工作中的实践;也感谢与我一起工作的同事们,非常荣幸能与你们一起在这个富有激情的团队中共同奋斗。
还要感谢Oracle公司虚拟机团队的莫枢,在百忙之中抽空审阅了本书,提出了许多宝贵的建议和意见。
最后,感谢机械工业出版社华章公司的编辑,本书能够顺利出版离不开他们的敬业精神和一丝不苟的工作态度。
周志明