我告诉你这书的第 3 版到底值不值得买?

持续输出原创文章,点击蓝字关注我吧

这是why的第 47 篇原创文章

荒腔走板

大家好,我是 why。老规矩,先是简短的荒腔走板聊聊生活。

上面的图是前几天拍的,那天晚上下班后,刚刚走进小区就看到了这一轮弯月和旁边那一颗特别特别亮的星星。

不知道为什么,一瞬间,我感觉一下回到了小时候的夏天。

脑海里浮现出了一些画面:一个大铁勺子舀一勺透心凉的井水、经过水缸冰镇的西瓜、树荫下卖樱桃的老爷爷、小河边嬉笑着抓螃蟹的同伴、提着一杯凉白开走在上学路上的自己,还有傍晚在顶楼纳凉的邻居们。

我小时候是在筒子楼长大的,一栋楼 7 层高,每一层住 10 来户人家。

那个时候没有谁家里有冰箱,但是家家户户都有一个大水缸。夏天,买一个西瓜回来,冲干净后扔在大水缸里面,晚上吃的时候,甭说多带劲了。

冰箱都没有,更别说空调了。所以到了夏天非常热,仅仅是靠一个吊扇是带来不了丝毫凉意的。大家就会不约而同的带着凉席、枕头、薄毯和蒲扇去顶楼睡一晚上。

而楼上楼下的邻居大多都熟识,大家就在顶楼上相互走动,坐在凉席上拉家常。

我特别喜欢在顶楼睡,在顶楼上睡的时候可以看到很多星星,还能听到窸窸窣窣的虫叫。

睡的时候爷爷还会给我讲故事,看到流星划过的时候记得许愿是爷爷告诉的我的。他还告诉我当一个人降生在这个世上,天上就会点亮一盏灯,这就是我们看到的星星。如果这个人要离开世界了,那么他的星星就掉落了,这个就是流星。

现在回想起来,我都是带着笑意的,我喜欢小时候的夏天。

好了,说回文章。

先说结论

自从《深入理解Java虚拟机(第 3 版)》发行后,我看到了很多人提出了相同的问题: 第三版值不值得买?

第二版和第三版我都看了,所以文本就是站在我个人的角来回答这个问题的。

《深入理解Java虚拟机(第 3 版)》,我是 19 年 12 月底买的。到现在基本上算是看完了。

现在,我终于有资格来回答类似这样的问题了:

也可以把之前说的这句话给实现了:

先说结论: 个人觉得很有必要。

据我分析,目前大概就是三类情况(前提都是你想看这个书)。

  1. 没有看过第二版。这种情况非常简单了,直接买第三版看就行了。没啥说的。

  2. 买了第二版,但是没翻过几次,甚至还没开封的。这种情况,我建议你直接把第二版收藏起来,买一本第三版回来看。不要舍不得还没翻过几次的第二版,就把时间“浪费”在第二版上。因为第三版的内容是包含了第二版,且对第二版进行了补充说明的,相当于是第二版 + 番外篇。所以,从时间收益的角度来说,直接看第三版是划算的。

  3. 之前买了第二版,也看过第二版的。我就属于这种情况,我的建议是看过第二版了,一定要再看看第三版,你就会知道,作者这本书出到第三版,不是圈钱的,是真的有干货,是真的在对知识进行更新。这是一种对技术的敬畏、对自己无愧、对读者的负责的态度。

这本书 2011 年出的第一版可以说是填补了国内 JVM 的一块空白。

2013年出的第二版可以说是推动了 JVM 在国内的普及度。

2019 年出的第三版在我看来更多的是反映出技术的更新换代之快速,在提醒着我们: 今日不学习,明日变垃圾。

我这么说吧: 要是没有这本书,也就没有这么多 JVM 的面试题。但要是真没有这本书,你的技术链上,会缺少了非常重要的一环。

同时,像书中的前言部分说的一句话:通常情况下,一个程序员只要了解了必要的 Java 类库 API、Java 语法,学习适当的第三方开发框架,就已经基本满足日常开发的需求了。

换言之就是,你如果不想当个普通的程序员,你应该了解一下书中提到的知识。

你细细的品一下,你是要面试题,还是要当个普通程序员,还是要技术的完善度?

第三版我也是期待已久:

说实在的,在第三版没出来之前,我也不知道有哪些内容。主要是第二版让我打开了 JVM 这扇大门,学习到了很多硬核知识、内功心法,第三版不论怎么样我都要支持一下。

现在看来,第三版并没有让我失望,它值得我这样去支持。

接下来,我就站在我自己的角度,给你详细的对比一下第二版和第三版的区别。

第三版 VS 第二版

首先,我们来个视觉上的直观对比:

如上图所示,第三版的一眼就看出来比第二版厚了不少。具体尺寸是什么呢。

我给大家量了一下。第二版厚度 2 厘米,而第三版厚度 2.7 厘米,比第二版足足多出来 7 毫米。

第二版 433 页,第三版 521 页,足足多出来了 88 页。

多了 88 页啊。你知道这意味着什么吗?

意味着关于 JVM 的面试题库,又丰富了近 10 万字啊。

再看看封面上的文字:

第二版的封面上赫然写着:基于最新JDK 1.7。

第二版周志明先生是 2011 年到 2012 年间写出来的,正式出版时间是 2013 年 9 月。而彼时,JDK 版本的最新版本是 1.7。

第三版的出版时间是 2019 年底,封面上说是:根据 JDK 新版本全面升级。

而当时,JDK 版本的最新版本是 13。

我写文章的此时,已经是 2020 年 5 月。2020 年 3 月 17 日,Oracle 公司正式发布了 JDK 14。

2011 年到 2020 年,这近 10 年的时间。

首先,JDK 版本的命名规则发生了变化。在 2018 年 3 月 JDK 10 版本发布后,JDK 的开发版本号弃用了以前的 1.x 的命名规则。

所以,我们也慢慢的从 JDK 1.7 改口变成了 JDK 7。

其次,虽然 2009 年 4 月 Oracle 公司就收购了 Sun 公司,Java 商标正式归 Oracle 所有。

但是在我的印象中,我读大学的时候,说到 Java 我更多的还是会想到 Sun 公司。而现在,一说到 Java,我的第一反应已经是从 sun 到变成了 Oracle。

这 10 年间,名字变了,版本号从 7 变成了 14 ,翻了一倍。甚至连所属公司都变了。

真的是,白云苍狗,换了人间。

好了,我们接着说说书里面的内容吧。

这两个版本的书都划分为五大部分:

  1. 走进 Java

  2. 自动内存管理

  3. 虚拟机执行子系统

  4. 程序编译与代码优化

  5. 高效并发

所以,我接下来的内容就主要顺着这五大部分去讲第三版对于第二版这五大部分增加了什么内容。

1.走进 Java

这一部分的内容主要就是 Java 技术的发展史。

就像我前面说的,第二版和第三版之间差的这近 10 年的时间,Java 已经发生了很多大事件,包括一些吃瓜群众喜闻乐见的事情。

比如, Android 对于 Java 的侵权案件在 2018 年尘埃落定, Google 赔偿了 Oracle 88 亿美金。

Google 心里苦啊。因为其实在 2017 年 Kotlin 就取代 Java 成为 Google 官方的 Android 一级开发语言了。未来取代 Android 的 Fuchsia 系统,更是和 Java 无瓜葛。

88 亿美金,心里苦啊。

还有一件吃瓜的事情就是 2018 年 9 月 25 日,JDK 11 发布。同时带来的一个轰动的谣言:Java 要开始收费啦!

一石激起千层浪,一谣言振奋了无数的标题党。

各大科技自媒体拿着键盘就冲进了战场,各种文章铺天盖地的而来。

也许我们当时都是拿不准结论的吃瓜群众,但是两年快过去了,我不需要说结果了,因为时间给了你答案。

上面写的两个事情都是我在第三版的书里面看来的,第二版没有这些内容。

这是第二版这一部分的 Java 技术发展的时间线插图,其实只写到了 2011-07-28,之后的内容都是展望:

这是第三版的插图:

同时这一部分还有一个小节是:展望 Java 技术的未来。

在第二版中,作者站在 2011 年展望的模块化、混合语言、多核并行、丰富语法、64 位虚拟机……这些东西都如约而至了。

在第三版中,作者是这样展望的:

可以说,我们站在 2020 年的时间节点上,往前再看 10 年,Java 的未来可期,我们的未来也同样一定是白云苍狗,换了人间。

但是是往好的方向还是差强人意的方向……这个就不好说。

哈哈哈,好了,下一部分。

2.自动内存管理

这一部分可以说是全书最重要、最 JVM 的部分,没有之一。

我犹记得当年第一次看这书看到这部分的时候首先看到的一句话:

墙外的人想进去,墙里的人想出来。

我看完之后,属于墙缝中一脸懵逼的人,不知道是应该进去还是应该出来。

这一部分是我做笔记,划线最多的一部分,基本上感觉是每句话都是考点,所以看的时候出现了很多类似于下面这种情况,一页全是划的线,因为感觉全是面试题:

这一部分是书中的重中之重,所以周志明先生也是在第三版中该部分下足了功夫。

这一部分又分为了 2 到 5 章。都很重要,所以,我们一章章的说。

首先第 2 章《Java 内存区域与内存溢出异常》,一上来就是王炸,我给你看张图你就明白了:

这一部分的开篇就抛出了这个经久不衰的“面试图”,你想想多少面试题都是从 这个图出发,然后问到你怀疑人生的?

而这一部分主要是围绕这几块区域来写,所以,很重要。

第三版相对于第二版而言,对很多地方进行了更加细致的补充说明,比如下面的两个版本对于 Java 堆的描述(左边第三版、右边第二版,我拍的,尽力了,可以点开看大图):

可以看到,在第二版中我框起来,并且用黑线标记了的地方,在第三版里面对于这些名词和区域划分进行了相当长的一段补充说明,确实是严谨了很多。

其他的区域描述变化不大,就不一一说明了。

但是有个变化是不得不提的,那就是在 JDK 8 里面已经没有了永久代的概念了,取而代之的是元空间的说法。

所以,在后面模拟方法区的溢出情况时,第三版专门新增了如下内容:

接下来,我们看看第3 章《垃圾收集器与内存分配策略》:

这部分,怎么说呢,简直哇塞了,重中之重的重中之重。

第二版里面看到 G1 收集器的时候,里面很多东西都没有讲明白。看完之后,也就只是落下了 G1 把内存“化整为零”的思想,感觉和前面介绍的几个垃圾回收器有显著的区别。

然后就剩下一些看不懂但是又感觉很重要的记忆集、卡表、写屏障这些名词。

这是可以理解的,周志明先生写第二版的时候, JDK 7 才刚刚发布没多久,G1 收集器还停留在实验室阶段,没有实际生产环境的数据去支撑。所以很多东西就写的比较模糊。

而在第三版中,对这一部分的内容我看了、也进行对比了,可以说是完全重新写了这一部分。

然后第三版中,还浓墨重彩的介绍了 JDK 11 和 JDK 12 中新出现的 ZGC 和 Shenandoah 这两款低延迟、全并发收集器的详细原理解析。

同时还简短的介绍了“标新立异“的不进行垃圾回收的垃圾回收器 Epsilon  

Shenandoah 和  Epsilon   我就不说了。ZGC 很有可能是下一批次的高频面试题,因为据官方态度,这就是垃圾收集器未来的发展方向。

这里就不展开说明了,总之很值得去学习一下。

除了垃圾收集器这部分对于 G1 的内容重写,新增 ZGC、 Shenandoah、Epsilon  内容外。

这一章节还新增了记忆集和卡表(用于解决跨代引用)、三色标记(引出并发标记问题)、增量更新和原始快照(为了解决并发标记问题)、写屏障( 量更新和原始快照 的实现原理)这些理论知识。

有了这些理论知识,对于 HotSpot 的设计的理解就更加容易一点。而这些,在第二版中是没有的。

好了,看一下两个版本第三章的目录对比吧(左边第三版,右边第二版):

左边第三版我用红框框起来的部分都是新增的内容。

第 4 章《虚拟机性能监控、故障处理工具》。这一章节是最实用的一小节。

两个版本都主要介绍了 JDK 自带的 6 个命令行工具,他们主要是:

  1. jps:虚拟机进程状况工具。

  2. jstat:虚拟机统计信息监视工具。

  3. jinfo:Java 配置信息工具。

  4. jmap:Java 内存映像工具。

  5. jhat:虚拟机堆转储快照分析工具。

  6. jstask:Java 堆栈跟踪工具。

第三版和第二版在这一章节的主要差异在于 JDK  可视化工具的介绍。

除了 JConsole、VisualVM 这两款工具外,第三版还额外介绍了 JDK 9 中新增的 JHSDB 调试工具:

然后还介绍了 Java Mission Control 这款可以持续在线的监控工具,工具的界面也是比较炫酷的:

它生成的报告包含下面几类信息:

然后还介绍了 HSDIS:JIT 生成代码反汇编。

这个工具还是很有用的,我之前写文章的时候分析代码就用到过,加上几个启动参数就可以输出汇编语言。

配合 JITWatch 工具,有奇效。可以直接看到 Java 源代码、字节码和即时编译生成的汇编代码,大概就是下面这个图的效果:

类似于普通人看代码,看到的是表层。用这个工具看代码,你可以看到程序的奇经八脉。

第 5 章《调优案例分析与实战》。

这一节中的几个案例分析,都是需要细细品读的,能从别人的实战中学到很多东西,前面的内容掌握了之后,看完案例你也会说一句:害,就这啊,学习了。

最后的对于 Eclipse 运行速度的调优,我的记忆也是很深刻的,因为当年第一次读到这里的时候就在我的电脑上实战了一番,确实是有些效果的。

3.虚拟机执行子系统

这一部分,首先讲了类文件的结构,无数英雄好汉都是在这个地方被劝退的。

第一次看完之后我也就记住了个 0xCAFEBABE 了。

什么字段表集合、方法表集合、属性表集合、各种字节码,统统都是关上书立马忘记的。

但是后来我发现了,这一部分的内容,没必要去记得那么牢吧。只要知道有这么一个东西,然后当遇到这个知识点的时候知道来这里翻一下书,就可以了。

换言之,这个地方可以当做工具书来看。

在类文件结构讲解完成后,进入了虚拟机类加载机制,我相信无数人接触“双亲委派模型”就是从这里开始的吧。

这一部分,第三版主要引入了 JDK 9 的模块化系统介绍。

由于 Java 模块化系统的引入,导致对类加载部分产生了巨大的影响。

如果说双亲委派模式在此之前有三次被破坏,分别是:

  1. 第一次是由于该模式是 JDK 1.2 之后引入的,导致的历史遗留问题。

  2. 第二次是模型自身缺陷,导致不能加载 SPI 接口。

  3. 第三次是为了追求代码热替换(Hot Swap)。

那么  JDK 9 的模块化就是对于双亲委派模式的第四次破坏。

可以给你对比一下:

你可以先自己品一品。具体的内容,去翻书吧。

4.程序编译与代码优化

这一部分在第三版中着重重新写了泛型的部分,描述了 Java 与 C# 里的泛型实现的方法,同时介绍了泛型出现的历史背景。当然,还有提到泛型就不得不提到的类型擦除。

语法糖,也是我在这本书的这一章节中学到的词。

前段时间很火的面试题:Java 所有的对象实例都在堆中分配内存,对吗?

在这一章节也有答案:

但是要特殊说明的是,需要注意书中的注脚:

其实你翻回去看书中对 Java 堆的介绍:

我做笔记的地方,书中写的是“几乎”、“不那么绝对”。你就知道,此事必有蹊跷。 

然后这一部分的第 11 章,名称发生了变化,从晚期(运行期)优化到后端编译与优化。(左边第二版,右边第三版)

同时,可以看到第三版新增了一个小节专门讲提前编译器的,分析了提前编译的优劣得失。

第三版还多了一个深入理解 Graal 的实战。

这玩意就厉害了,之前写文章的时候准备阶段也用过这个工具。用作者的话说: 写到这里,笔者忍不住感慨, Graal 编译器的出现对学习和研究虚拟机代码编译技术实在有着不可估量的价值。

5.高效并发

这一部分的内容主要是讲 java 内存模型(JMM)和线程以及线程安全和锁优化部分。

这一部分由于变化不大,我就不做过多的介绍了,其实我觉得这部分的内容和 JVM 以及不是紧密相关了,只是一个扩充内容。

如果需要更多的了解多线程编程的技术,还是需要去阅读其他的专门描述多线程编程的书籍。

第三版在这个部分,多介绍了 Java 未来基于协程的新并发模型。

Java 支持协程应该是非常困难的了。比如说个简单的:协程中遇到传统的线程同步措施应该怎么去处理?

很难去解决这种棘手的问题。

但是 Java 的解决方案是纤程。具体是什么我就不说了,有兴趣的去翻翻书吧。

其实这块不知道我觉得影响也不大,因为在我短短的程序员职业生涯中,我觉得我应该还不会和纤程打交道。属于有生之年系列。

如果你知道了呢?

那么恭喜你,朋友,又学到了一个基本上用不到的知识点。

好了,上面的内容,我从五大部分去分析了第三版的新增内容。

接下来,我送你书中我发现的 5 个彩蛋吧。

五个彩蛋

当然,这五个彩蛋是对我而言的,从我个人的角度出发,对我是彩蛋,每个人的看法都不一样。

先说明一下,我的第二版是 2016 年 5 月第 13 次印刷。第三版是 2020 年 1 月第 1 次印刷。印刷版本不一样,可能有细微差别。

彩蛋一

在书的开篇。

第二版说:时至今日,Java 技术体系已经吸引了 900 多万软件开发者,这是全球最大的软件开发团队。

第三版说:时至今日,Java 技术体系已经吸引了 600 多万软件开发者,这是全球最大的软件开发团队。

第二版写于 2011 年,第三版写于 2019 年,短短 8 年的时间,少了 300 多万从业者。

作者说他的数据来源于 Java 的广告词。我不知道是统计维度的变化导致的 300 多万的差距,还是真的就是少了这么多人。

彩蛋二

2.4.3 小节(方法区和运行时常量池溢出):

彩蛋藏在第三版的注脚中。为此,我还专门写过一篇文章,有兴趣的可以去阅读一下。

《深入理解Java虚拟机》第2版挖的坑终于在第3版中被R大填平了

彩蛋三

在第 3 章《垃圾收集器与内存分配策略》中第二版和第三版中一个描述不一样(上面是第二版,下面是第三版):

很明显,上面第二版的描述中对于 Full GC 的描述是错误的。

但是巧就巧在我一次面试的过程中,一个面试者说 Full GC 是指老年代 GC,说的那叫一个信誓旦旦。他说在书里面看到的。

我回来一翻书,发现还真是这样的,可惜这个地方写的有点问题,在第三版中进行了重新描述,Full GC 一定是整堆收集的,朋友们。

后面也有人在我的文章中评论过相关问题,我也是用这个彩蛋回答的。

彩蛋四

第五部分,关于线程状态的描述,第二版中有个笔误,把 6 种状态写成了 5 种,第三版中修复了过来(下图中,上面是第二版,下面是第三版):

但是我发现第三版的状态图画的又有问题了(左边第三版,右边第二版):

第二版的状态图是没有问题的,第三版中:New 到 Running 之间和 Running 到 Terminated 之间是双箭头,这是不对的。

彩蛋五

第三版,312页,在讲动态分派的知识点的时候有这么一点示例代码:

很明显,作者想写的是 guy,手抖打成了 gay 。问题不大,就是有点怪怪的。

一个笔误带来的小彩蛋。

我与JVM的故事

然后,分享一下我和 JVM 之间的故事吧。

毫不夸张的说,我刚刚毕业的时候对于 JVM 是完全不了解的。仅限于听说过这个词。

大三的时候在外实习了一年,写了一年的 CRUD (增删改查),做了两个外包的政府项目,其实所有的需求都不复杂,都是可以通过增删改查几个接口的组合实现的。

所以一年以后,我觉得程序员好像也不是那么难,CRUD 写的那叫一个炉火纯青。膨胀到觉得靠着这一身 CRUD 的硬本领,我可以去北京闯一闯。

幸好,2016 年找工作的时候 JVM 的面试题感觉好像还不是特别的普及,至少对于一个刚刚毕业的应届生而言,所以面试了好几家公司,都没有问一个 JVM 相关的试题。

后来,我比较顺利的进入了一家公司。加入这家公司的两个月后,就是长达 7 天的国庆节。

在国庆之前,我买了这本书。国庆七天没有出门,把第二版撸完了一遍。

啃的是异常的艰难,可以说是囫囵吞枣。很多东西完全是靠死记硬背,打开书,什么都知道。一合上书:刚刚看的是啥来着?

我相信很多朋友第一次看这书的时候和我的感觉都差不多。现在回想起来都是很正常的,都说了是内功心法了,仅仅不到一年的工作经验很难去修炼这种上乘武功的。

只是随着工作经验的增加,加上对于不懂的地方我进行了反复阅读,最后才算是懵懵懂懂,感觉是吸收了一点点,可以应付一下面试了。

等到后面通读了几遍后。你会发现,这书就算你读了百遍,其意也没有自见。仅仅是带你进入了 JVM 的大门而已。

当然,我不是说这本书不好,而是 JVM 本来就是一个很有难度的学科。不是你读一两本书就能搞明白的,它仅仅是一个带你入门的角色。

门里面的世界,与我而言,深不见底。

比如我之前写过几篇 JVM 相关的文章,后来有读者来问我由文章延伸出来的问题,我也不知道:

我写的时候接触到了这部分的知识,但是翻阅了一下相关资料,发现是异常复杂的,所以我也就没有深入研究下去了。

我举这个例子的目的是说: JVM 是学无止境的,当然你背几道面试题也是能够应付过去的。但是你真的不想真正的了解的更多一点吗?武林秘籍就摆在你眼前,你不想去翻一翻吗?

其实,从我入行到现在,4 年时间,每年我都能看到“新”的 JVM 的文章出现。而这些“新”的 JVM 文章里面装的都是一些老酒。

当然我不是说这样不好。这样没有问题,每年的“新”文章都是别人看了相关知识后自己总结出来的,分享了出来,而我们看到了也是可以温故而知新的,这样是双赢。

只是,我们为什么不直接从源头看起呢。源头说来说去也不外乎就那几本书而已,其中就包含文章说的这本。

最后分享一下我看这书的一个小小的转变吧:

2016 年我第一次读这书的时候,虽然看不懂,但是觉得这简直就是圣经啊!

2020 年的现在,我有了一点工作经验,读了几次这书后,衍生了其他的知识点后,才发现,这本书其实就是个科普入门级别而已。

没有不敬的意思,而是 JVM 真的是一门博大精深的学问。而任何一门博大精深的学问都不可能是你看一两本书就能掌握的,只能说是入门。

而且永远也别想着读一遍就能把这本吸收完,说实在的,你能完整的读完一遍就算不错了。

当你凝望深渊的时候,深渊也在看着你。当你学习 JVM 的时候,JVM 也在拉着你“越陷越深”。

总之,我还是很推荐购买的,对了,最近当当也在搞 5 折优惠,可以去看一下。

最后说一句

这篇文章感觉像是一篇软文似的,但是没有关系,我就是这个书的自来水。总体上来说,这是一本值得被更多人知道的书。

点个“在看”吧,周更很累的,不要白嫖我,需要一点正反馈。

才疏学浅,难免会有纰漏,如果你发现了错误的地方,由于本号没有留言功能,还请你加我微信给我指出来,我对其加以修改。(我每篇技术文章都有这句话,我是认真的说的。)

感谢您的阅读,我坚持原创,十分欢迎并感谢您的关注。

我是 why,一个仅仅写了几篇文章的程序猿,不是大佬,但是喜欢分享,是一个又暖又有料的四川好男人。

往期回顾

每天都在用,但你知道 Tomcat 的线程池有多努力吗?

如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。

【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。

面试官:你回去等通知吧!

G1回收器:我怎么知道你是什么时候的垃圾?

欢迎关注我的公众号【why技术】,这号主要进行一些技术分享:

同时也可以关注我的另外一个号【why不止技术】哦,这个号主要负责荒腔走板聊生活、品人生、写书评、谈电影的部分:

有读者叫我把这个放在赞赏之后,结果放不了。

但我还是非常感动,感谢读者提出的各种建议。

点亮”在看”,别白嫖我,好 吗?