本书主要展示了如何在当今先进的多核硬件和复杂的操作系统环境下,系统且主动地提高Java 性能。
本书对Charlie Hunt 和Binu John 的经典图书Java Performance 进行延伸,提供了两个前所未有的、强大的Java 平台创新细节:Garbage First(G1)垃圾收集器和HotSpot 虚拟机服务代理。
阅读本书,你就可以在任何情况下从JDK8 或9 中发挥Java 的最大性能。
G1 | HotSpo 前所未有的创新 突破多核硬件|复杂环境下性能极限
推荐序1
若干年前,Charlie Hunt出过一本Java之父Gosling欣然作序推荐的Java TM
Performance,我现在还记得推荐语中那些星光熠熠的名字——Azul的R大莫枢,阿里花名叫毕玄的林昊,《深入理解Java虚拟机》的作者周志明等等。
若干年后,Charlie Hunt又出了它的姊妹篇Java Performance Companion(中文书名为《Java性能调优指南》)。 这次轮到我被春雨邀来作序,深感荣幸。
与前一本大而全的Java调优圣经相比,这本薄薄的姊妹篇只深入讲解了两件事情:一是很多人知道但并不太精通的G1垃圾收集算法,另一个是JDK自带的,强大但鲜有人知,面试里问谁谁死的工具——HotSpot Serviceability Agent。为什么要单挑这两点来出一本书呢,大概是作者觉得一线的Java性能调优工程师以及负责Trouble Shooting的大神,都需要掌握这些细节,而目前已有的书籍和文章,又达不到作者期望的深度吧。
与Java程序员相依相伴了很多年的CMS垃圾收集算法,随着现在Java应用的内存越占越大的情况,在暂停时间上有点力不从心了。但压测的经历告诉我们,不是简单地把算法改成G1就可以。从十年前G1理论的提出,到在JDK8里真正可用,JVM的工程师们反复打磨了漫长的时光,可见其实现是相当复杂的。如果真的在生产环境对延时敏感严苛的应用上使用它,你需要了解更多的实现细节,更多的优化技巧,才能有足够的信心去把控未来可能出现的情况——本书正好提供了这方面的内容。
而另一个SA就更好玩了。大部分负责火线处理状况的工程师都会用Thread Dump、 Heap Dump 、BTrace来获取JVM和应用的状态,偶然间,我也在R大指导下,用过gdb来查找线程死锁的原因。其实,JDK还为这些苦恼的救火员们,准备了另一份强大的分析工具——SA及其可视化的工具HSDB。可惜搜遍互联网,也就只有R大写过一篇介绍,还有寒泉子和占小狼写过使用的案例。希望凭这本书,能多制造出几个在自己公司里充当定海神针的大神来。
如果我没有加入唯品会的基础架构部,也不会每天睁眼就面对各种服务调用超时、GC暂停、并发锁或其他不可描述的奇怪状况,也不会获得如此多的锻炼和感悟。我有感于此,希望有更多的Java程序员,在业务代码开发之外,永远对性能优化,对优雅代码,保持自己的欲望;对各种意外情况,保持好奇心而不是恐惧感。最后做个广告(嗯,侠少答应的写序的福利),我的所有这些Java工作的日常与思考,都会写在个人微信号“春天的旁边”里,欢迎来访。
肖桦(江南白衣)
唯品会高级架构师
推荐序2
侠少邀请我为本书写序已经挺久了,直到2017年春节假期之后才开始动笔,再拖都有点过意不去了,在此还是要感谢下侠少及博文视点对我的信任和包容。
本序主要分为两部分,一部分是对本书的内容做一个大致的介绍,另外一部分是简述下本人走上JVM这条路的心路历程。
收到本书样稿之后满怀期待地看了起来,当我第一次看到目录时还是震惊了一下,因为本书的重点在G1 GC和SA,两者实际上并没有多大关系,将它们俩合在一起写成此书,本人觉得挺新鲜的,而且本书有且仅有这两者,不过再想想这本书的名字,其实也合情合理。
G1 GC是HotSpot重点发展的GC算法,和其他GC算法最大的区别是弱化了分代的概念,引入了分区的思想,从JDK8开始算比较稳定了,官方也推荐大家使用G1 GC来替代CMS GC,是未来大家首选的GC算法。尽管G1希望能做到自适应,但是毕竟每个系统的特性不一样,最终可能仍然省不了参数调优的活,本书从实现的角度来阐述了这个算法的各个细节,另外值得一提的是,书中提到的细节完全可以映射到代码中来一起看,它将带您一步步揭开G1 GC的神秘面纱。另外我曾有幸和本书的作者之一——Monica有过一面之缘,她谈及对G1的理解还是让我挺惊讶的。
SA作为JDK自带的一款优秀的分析工具,本身就是用Java实现的,所以它可以让JVM里的数据结构直接以Java的形式暴露在您面前,比如说我们方法调用会创建一个栈帧,那这个栈帧在JVM里是怎样的结构?又比如我们想要获取运行时加载的类的字节码,都可以直接通过API获取到。另外本书还介绍了一个重要的图形化工具HSDB,它是基于SA实现的,可以让您更直观地看到对象在VM里的数据结构以及对象依赖和被依赖的关系等,这个工具在我们在平时查问题的时候提供了极大的便利,可以这么说吧,如果您熟悉SA的数据结构,那您对JVM的数据结构也算清晰了解了,它为我们Java开发者打开了学习JVM的另外一扇大门。
接下来说说我的经历吧,其实我算不上JVM领域的前辈,更谈不上JVM领域的精英,说是JVM领域的一个新手一点不为过。阿里是我2010年大学毕业后的第一份工作(目前我还一直在支付宝),它是一个Java王国,对Java重度依赖,然而我在进阿里之前对Java其实并没有进行太深入的学习,可以说了解的非常少,主要技能集中在Flex/Flash/ActionScript领域,现在没有进入前端界其实还是有点小遗憾的,因为一直都喜欢所见即所得的这种感觉。进入支付宝之后我从事的是Java框架研发的偏基础性质的工作,一干就是三四年,非常感谢这段宝贵的经历,让我从前端过渡到了后端,同时让我有足够多的机会碰到各种中间件周边技术的疑难杂症,并不断尝试去解决他们。后面我们框架做大版本升级改造,迁移到标准的OSGI容器equniox上来,于是碰到了大量的类加载问题,譬如ClassNotFoundException、LinkageError等这些问题,如果对类加载机制不是很熟悉还是比较难解决的,我们当时仅仅对JDK层面的类加载机制熟悉,深入到JVM里的实现就完全是个黑盒了,类似LinkageError这种问题在您看了JVM里的实现之后才可能有更深的理解,就这样一个偶然的机会开始下载OpenJDK代码,并研究起JVM来,不过说来也奇怪,在此之后公司碰到的JVM的问题感觉也越来越多了,比如内存溢出、频繁GC、系统卡死等。我在2014年年底的时候正式加入到了阿里JVM团队,开始了真正的JVM探索之旅。
在探索JVM的过程中,我基本是问题驱动型的,因为我们在平时工作过程中也很容易碰到很多JVM相关的问题,通过一个个攻破这些问题从而积累了不少实践经验,对实现原理也慢慢地熟悉起来,针对一些比较有代表性的文章,我常常会将解决思路记录成文保存下来,并通过个人博客(http://lovestblog.cn),个人微信公众号(“你假笨”),或者阿里内部的ATA技术论坛等进行传播,希望这些经验能帮助到更多的人,让他们少走弯路,更多的精力能花在他们自己的业务开发上面。
你假笨
阿里JVM专家寒泉子
译者序
早些年用C/C++做开始时,内存管理错误一直是程序员们(包括我)在开发中面对的最大的困扰之一,各种内存方面的怪异问题经常把人折磨的欲仙欲死,当然我也不否认Debug过程极其有效的帮助我更深入的学习了内存管理机制。在最初转向Java开发时,我觉得就像笼罩在头上几十年的雾霾一下都不见了,要对象是吗?来吧,new一个。再也不用管要不要或什么时候free或delete。 但随着了解的不断深入,我们发现天底下真的没有免费的午餐,有所得也就必有所失。在享受垃圾收集器的便利的同时,也许你就要忍受其带来效率的降低(原因有很多,比如配置不当)。而且这些年垃圾收集的技术一直在持续发展,是否采用垃圾收集?采用何种垃圾收集?如何调优?等等。一系列的问题,慢慢成为架构设计时就要考虑的问题,而不再仅仅是“自动回收内存”那么简单。于是乎,深入了解垃圾收集技术,就十分必要了。
垃圾收集技术本身不是一个新技术,各种效率方面的质疑与探讨也不是什么新话题,而垃圾收集器本身也发展了一代一代又一代。但很多开发人员因为工作原因本身,停留在知其然而不知其所以然的层面上。而本书,针对Java G1垃圾收集器以及调试诊断方面,做了全面而深入的总结,而专注于G1的书籍目前几乎是个空白,本书的出现恰好弥补了这方面的内容。本书的发起者及作者之一的Charlie Hunt,其也是Java应用性能调优圣经《Java性能优化权威指南》的作者,他曾任Oracle公司首席JVM性能工程师,负责HotSpot Java虚拟机和Java SE类库性能的改进。而其他几位作者同样在G1垃圾收集器方面有非常深厚的功底和丰富的调优经验。本书作为《Java性能优化权威指南》的姊妹篇,内容可能不如其那么丰富,但本书在G1的细节方面会更加的深入与广泛。
作为译者,我已经尽可能地避免错误和疏漏出现在译本中,不过由于译者本人能力有限,书中难免有些不妥之处,希望广大读者与同行批评指正。
最后要感谢电子工业出版社的张春雨老师与倩雪编辑,感谢他们在我翻译过程中给予的帮助和包容。同时还要感谢家人和朋友的宝贵支持,这段时间基本处于失联状态,现在我胡汉三又回来啦。谢谢你们。
李源
途牛旅游网供应链研发中心总经理
前言
欢迎来到Java性能调优指南。本书为JavaTM Performance1提供了配套教程,其首次发行于2011年9月。尽管本书涉及的附加主题的内容不如JavaTM Performance那么丰富,但会更加广泛地深入细节。本书涉及到的主题有G1垃圾收集器,也称作“Garbage First垃圾收集器”,以及Java HotSpot VM Serviceability Agent。本书附录中还包含了一些额外的HotSpot VM命令行选项,它们没有被包含进JavaTMPerformance关于HotSpot VM Serviceability Agent命令行选项的附录中。
如果你正在使用Java8,有兴趣迁移到Java8,或者计划使用Java9,有很大可能是要么在评估G1垃圾收集器,要么已经在使用它。因此,本书中的信息将对你有很大帮助。如果你有兴趣诊断意料之外的HotSpot VM失败原因,或者学习更多有关现代Java虚拟机的细节,本书中关于HotSpot VM Serviceability Agent的内容也将对你很有用。不仅是HotSpot VM开发者,对于那些日常工作包含定位以及排除HotSpot VM故障行为的Oracle支持工程师来说,HotSpot VM Serviceability Agent都是他们的可选工具。
本书从G1垃圾收集器的概述开始,通过提供为什么G1作为一个垃圾收集器被开发出来并被包含进HotSpot VM中的背景,接着是关于G1垃圾收集器是如何工作的概况。紧随其后的是2个关于G1的附加章节。第1部分是对G1内部的深入描述。如果你已经很好地理解了G1垃圾收集器是如何工作的,并且有进一步调优G1的需求,或者想要知道更多它的内部工作,那么这一章将是一个很好的着入点。第3章讲述了如何针对你的应用程序进行G1调优。G1的主要设计点之一就是能简化实现良好性能所需的调优工作。举例来说,主要输入G1的是可用的初始且最大的Java堆尺寸,以及你可以容忍GC暂停的最长时间。通过这些输入,当执行你的应用程序时G1将尝试自适应地调整来满足它们。如果你想要获得更好的性能,或者想要在G1上做一些额外的调优,就可以在这一章节找到你想要的信息。
最后一章完全专注于HotSpot VM Serviceability Agent。这一章节会提供一个如何使用SA的深入描述和说明。如果你有兴趣了解更多关于HotSpot VM的内部原理或者如何诊断和排除HotSpot VM的意外问题,那么这一章节正是为你准备的。在本章节中你将会通过案例及说明学习如何利用HotSpot VM Serviceability Agent用不同方式观察和分析HotSpot VM行为。
最后,附录中包含了一些HotSpot VM命令行选项,它们没有被包含在JavaTM Performance中关于HotSpot VM命令行选项的附录里。在附录中的许多HotSpot VM命令行选项都与G1相关。我们建议在合适的时间尝试使用这些选项,而不是仅仅把它们列在清单上。
1、并行垃圾收集器一节第3行,“对相关的应用来说”,原文是relative to application work,应该翻译成“相对于应用执行花费时间来说”
2、并行垃圾收集器一节第11行,激活“并发”垃圾收集器,并发应该是并行
贴士中的“- XX:+UserParallelOldGC”应该没有空格
“-XX:+CMSParallelInitial Mark Enabled”中间没有空格,应该是“-XX:+CMSParallelInitialMarkEnabled”
“XX:+UseConcurrentMarkSweepGC”前面少了连字符,而且没有这个选项,应该是“-XX:+UseConcMarkSweepGC”
第一个分区别被标记为…,其他的分区别被标记为…
去掉别字。