
前言
起初O'Reilly公司让我写一本关于Java性能调优的书时,我还不确定是否值得写。我在想,难道Java性能调优我们做得还不够吗?事实上,虽然我日常的基本工作是Java(和其他)应用程序的性能调优,但我宁愿将大多数时间都花在提高应用程序的算法效率以及处理外部系统的性能瓶颈上,而不是直接进行Java自身性能的调优。
但转念一想,我不禁哑然失笑(像往常一样)。的确,我的大量时间都花在了端到端的系统性能调优上,有时会发现那些原本可以用O(log N)却用了O(n2)算法的代码。不过这也说明,我每天考虑的都是GC调优、JVM编译器的性能调优,或者是如何使Java EE API的性能发挥到极致。
说这些并不是想要抹杀过去15年里Java和JVM在性能上取得的巨大进步。1990年代晚期,我在Sun公司担当Java布道师,当时仅有的真正意义上的“基准测试”工具来自Pendragon软件的CaffeineMark 2.0。由于种种原因,该基准测试工具设计上的不足很快就限制了它的价值;然而在那个年代,我们总喜欢告诉所有人,依据这个基准测试,Java 1.1.8的性能比Java 1.0快八倍。这并非耸人听闻——Java 1.1.8已经有了真正的即时编译器,而Java 1.0差不多完全是解释型的。
之后,Java标准委员会开始制定更严谨的基准测试,Java的性能测试开始围绕这些基准测试展开。最终,JVM的所有领域——垃圾收集、编译器和API都获得了长足的进步。这个过程一直延续到今天,而关于性能的一个重要事实是,调优正变得越来越艰难。引入即时编译器后所获得的八倍性能提升,只是一个简单的工程问题,即使编译器持续改进,我们也无法再次看到如此巨大的改进了。并行化垃圾收集也曾极大地提升过性能,但最近的变化则是渐进式的。
这是典型的应用发展过程(JVM本身也是另外一个应用):在项目初期,很容易找到架构上的改进点(或代码缺陷),一旦找到就能极大改善性能。而在成熟应用中,要找到这样的性能改进点则很罕见。
起初我觉得,从很大程度上说,Java性能调优都已经工程化了,但有几件事情让我相信我错了。首先,我每天在特定环境下运行JVM时,都会遇到许多这样或那样的问题。新工程师源源不断地进入Java领域。在特定的领域,JVM的行为仍然相当复杂,因此有份描述它如何运作的指南很有必要。其次,现在的计算环境发生了变化,已经影响到了工程师们所面临的性能问题。
在过去几年中,性能关注点有了分歧。一方面,有大量内存堆可运行JVM的大机器现在已经很普遍了。为了应对这样的变化,JVM也有了新的垃圾收集器(G1)——这项新技术相比传统的收集器更需要手工调优。同时,云计算又提升了单CPU的小机器的重要性:你可以从Oracle、Amazon或其他公司以非常便宜的价格租用单CPU机器,运行小的应用服务器。(你获得的并不是真的单CPU机器,而是一台巨大机器上的一个虚拟OS镜像,但虚拟OS被限制为使用单个CPU。从Java角度看,它和单CPU的机器相同。)在这些环境中,正确管理小量内存变得非常重要。
Java平台也在持续演变。Java的每个新版本都会提供新的语言特性和新的API,这些特性和API并不总是为了提高应用性能,也是为了改善开发人员的生产率。语言特性运用得好,应用的运行就会变得轻快,反之则缓慢笨重。另外,平台的演化也带来了一些重要的性能课题:毫无疑问,程序间用JSON交换信息要比用高度优化的私有协议更容易。节约开发人员的时间就是巨大的收益——但真正的目的是确保生产率提升的同时,性能也能提升(至少是两者之间取得平衡)。
读者对象
本书适合那些渴望深入了解JVM和Java API性能各个方面的性能调优工程师和开发者。
假如你想快速修复性能问题,比如网站周一早上要上线,而现在已经是周日深夜了,那么本书可能不适合你。
如果你是性能分析的新手,正要开始进行Java的性能分析,那么本书会对你有所帮助。我的目的主要是为新工程师提供足够多的信息和上下文,以便使他们明白如何将基本的性能调优原则运用到Java应用中去。然而,系统分析的范畴非常广阔,已经有大量的优秀资源(那些原则当然也适用于Java),从这个意义上来说,希望本书也能成为它们的有益补充。
不过从根本上说,想让Java运行得飞快,就得深入理解JVM(以及Java API)的实际工作原理。有数以百计的Java性能调优参数,而JVM调优并不像瞎猫碰死耗子那样,调一下再看看是否奏效。与之相反,我的目的是提供更为详尽的JVM和API工作原理,以期在你理解它们如何工作的原理之后,能理解应用的某些行为为何糟糕。理解了这些之后,排除那些性能低下、令人不快的行为就会变成简单(至少是比以前更简单)的任务。
Java性能调优工作还有一个有趣的方面,就是开发人员的背景和性能调优或QA组人员的背景常常有很大差别。我认识一些开发人员,他们可以记住成千上万个令人费解的很少使用的Java API方法签名,但他们对-Xmn的含义却没有什么概念。我也认识一些测试工程师,他们可以通过设置垃圾收集器的各种标志来榨取最后一滴性能,但他们却很少有人能用Java写出像样的“Hello, World”。
Java性能调优覆盖这两个领域:编译器和垃圾收集器等的调优参数,以及API的最佳实践。所以,我假定你对如何编写Java程序有很好的理解。即便你主要的兴趣不是在Java编程,我仍然会花一点时间讨论编程,包括例子中包含大量数据的示例程序。
然而,如果你的主要兴趣是JVM自身的性能调优——意思是不用更改任何代码而改变JVM的行为,那么本书的大量章节都对你有用。可以随意跳过代码部分,而关注你所感兴趣的领域。也许你会顺便为Java应用如何影响JVM性能提出一些真知灼见,并向开发人员提出更改建议,以便让你的性能调优测试工作更加如鱼得水。
排版约定
本书使用的排版约定如下。
• 楷体
表示新术语。
• 等宽字体(constant width)
表示程序片段,以及正文中出现的变量、函数名、数据库、数据类型、环境变量、语句和关键字等。
• 等宽粗体(constant width bold)
表示应该由用户输入的命令或其他文本。
• 等宽斜体(constant width italic)
表示应该由用户输入的值或根据上下文确定的值替换的文本。
这个图标代表提示或建议。
这个图标代表重要说明。
这个图标代表警告或提醒。
使用代码示例
可以在这里下载本书随附的资料(代码示例、练习题等):https://github.com/ScottOaks/JavaPerformanceTuning。
让本书助你一臂之力。也许你需要在自己的程序或文档中用到本书中的代码。除非大段大段地使用,否则不必与我们联系取得授权。例如,无需请求许可,就可以用本书中的几段代码写成一个程序。但是销售或者发布O'Reilly图书中代码的光盘则必须事先获得授权。引用书中的代码来回答问题也无需授权。将大段的示例代码整合到你自己的产品文档中则必须经过许可。
使用我们的代码时,希望你能标明它的出处,但不强求。出处一般包括书名、作者、出版商和ISBN,例如:Java Performance:The Definitive Guide by Scott Oaks(O'Reilly,2014). Copyright by Scott Oaks, 978-1-449-35845-7。
如果还有关于使用代码的未尽事宜,可以随时与我们联系:permissions@oreilly.com。
Safari®Books Online

Safari Books Online(http://www.safaribooksonline.com)是应需而变的数字图书馆。它同时以图书和视频的形式出版世界顶级技术和商务作家的专业作品。
Safari Books Online是技术专家、软件开发人员、Web设计师、商务人士和创意人士开展调研、解决问题、学习和认证培训的第一手资料。
对于组织团体、政府机构和个人,Safari Books Online提供各种产品组合和灵活的定价策略。用户可通过一个功能完备的数据库检索系统访问O'Reilly Media、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett、Course Technology以及其他几十家出版社的上千种图书、培训视频和正式出版之前的书稿。要了解Safari Books Online的更多信息,我们网上见。
联系我们
请把对本书的评价和问题发给出版社。
美国:
O'Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
中国:
北京市西城区西直门南大街2号成铭大厦C座807室(100035)
奥莱利技术咨询(北京)有限公司
O'Reilly的每一本书都有专属网页,你可以在那儿找到本书的相关信息,包括勘误表、示例代码以及其他信息。本书的网站地址是:
http://oreil.ly/java-performance-tdg。
对于本书的评论和技术性问题,请发送电子邮件到:bookquestions@oreilly.com
要了解更多O'Reilly图书、培训课程、会议和新闻的信息,请访问以下网站:http://www.oreilly.com
我们在Facebook的地址如下:http://facebook.com/oreilly
请关注我们的Twitter动态:http://twitter.com/oreillymedia
我们的YouTube视频地址如下:http://www.youtube.com/oreillymedia
致谢
感谢在我写这本书时所有帮助过我的人。从各方面来看,这本书汇集了我过去15年来在Sun公司和Oracle公司的Java性能调优小组中的所学所知。如果将为这本书提出真知灼见的人都列出来的话,会是一份长长的列表。感谢在那段时间与我一同工作的工程师们,特别是在那些年里耐心回答我铺天盖地的问题的人们。
我要特别感谢Stanley Guan、Azeem Jiva、Kim LiChong、Deep Singh、Martijn Verburg和Edward Yue Shung Wong,感谢他们拨冗审阅本书的初稿,感谢他们提供的宝贵意见。虽然本书因为他们的建议而完善了许多,但我相信错误仍然在所难免。
O'Reilly的工作人员总是那么乐于助人,感谢我的编辑Meg Blanchette,感谢你在整个写作过程中的鼓励。最后,衷心感谢我的丈夫James给予我在为书而抓狂的漫漫长夜里的悉心陪伴,以及周末晚餐。