描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787121367748
★结构清晰。
采用从整体到局部的视角,每一章节对应单独的知识点,力求展示虚拟机的全貌。
★理论结合实战。
在每一个知识点后,都给出了演示示例供读者参考,帮助读者更好地消化
★专注专业。
对Java虚拟机的原理和实践做了丰富介绍,力求从多角度更专业地对JVM进行探讨。
★通俗易懂。
本书服务于广大虚拟机初学者,简单的白话文风格贯穿全书,使读者少盲点、无盲点。
★技术全面。
纵横Windows和Linux双系统下的性能诊断、涉及32位系统和64位系统的优化比较、贯穿从JDK 1.5到JDK 10的优化演进。
第1章 初探Java虚拟机 1
1.1 知根知底:追溯Java的发展历程 2
1.1.1 那些依托Java虚拟机的语言大咖们 2
1.1.2 Java发展史上的里程碑 2
1.2 跨平台的真相:Java虚拟机做中介 4
1.2.1 理解Java虚拟机的原理 4
1.2.2 看清Java虚拟机的种类 5
1.3 一切看我的:Java语言规范 6
1.3.1 词法的定义 6
1.3.2 语法的定义 7
1.3.3 数据类型的定义 8
1.3.4 Java语言规范总结 9
1.4 一切听我的:Java虚拟机规范 9
1.5 数字编码就是计算机世界的水和电 10
1.5.1 整数在Java虚拟机中的表示 10
1.5.2 浮点数在Java虚拟机中的表示 12
1.6 抛砖引玉:编译和调试虚拟机 14
1.7 小结 18
第2章 认识Java虚拟机的基本结构 19
2.1 谋全局者才能成大器:看穿Java虚拟机的架构 19
2.2 小参数能解决大问题:学会设置Java虚拟机的参数 21
2.3 对象去哪儿:辨清Java堆 22
2.4 函数如何调用:出入Java栈 24
2.4.1 局部变量表 26
2.4.2 操作数栈 31
2.4.3 帧数据区 31
2.4.4 栈上分配 32
2.5 类去哪儿了:识别方法区 34
2.6 小结 36
第3章 常用Java虚拟机参数 37
3.1 一切运行都有迹可循:掌握跟踪调试参数 37
3.1.1 跟踪垃圾回收—读懂虚拟机日志 38
3.1.2 类加载/卸载的跟踪 42
3.1.3 查看系统参数 45
3.2 让性能飞起来:学习堆的配置参数 45
3.2.1 最大堆和初始堆的设置 46
3.2.2 新生代的配置 49
3.2.3 堆溢出处理 53
3.3 别让性能有缺口:了解非堆内存的参数配置 54
3.3.1 方法区配置 55
3.3.2 栈配置 55
3.3.3 直接内存配置 55
3.4 Client和Server二选一:虚拟机的工作模式 58
3.5 小结 59
第4章 垃圾回收的概念与算法 60
4.1 内存管理清洁工:认识垃圾回收 60
4.2 清洁工具大PK:讨论常用的垃圾回收算法 61
4.2.1 引用计数法(Reference Counting) 62
4.2.2 标记清除法(Mark-Sweep) 63
4.2.3 复制算法(Copying) 64
4.2.4 标记压缩法(Mark-Compact) 66
4.2.5 分代算法(Generational Collecting) 67
4.2.6 分区算法(Region) 68
4.3 谁才是真正的垃圾:判断可触及性 69
4.3.1 对象的复活 69
4.3.2 引用和可触及性的强度 71
4.3.3 软引用—可被回收的引用 72
4.3.4 弱引用—发现即回收 76
4.3.5 虚引用—对象回收跟踪 77
4.4 垃圾回收时的停顿现象:Stop-The-World案例实战 79
4.5 小结 83
第5章 垃圾收集器和内存分配 84
5.1 一心一意一件事:串行回收器 85
5.1.1 新生代串行回收器 85
5.1.2 老年代串行回收器 86
5.2 人多力量大:并行回收器 86
5.2.1 新生代ParNew回收器 87
5.2.2 新生代ParallelGC回收器 88
5.2.3 老年代ParallelOldGC回收器 89
5.3 一心多用都不落下:CMS回收器(JDK 8及之前的版本) 90
5.3.1 CMS主要工作步骤 90
5.3.2 CMS主要的参数 91
5.3.3 CMS的日志分析 93
5.3.4 有关Class的回收 94
5.4 未来我做主:G1回收器(JDK 9及之后版本的默认回收器) 95
5.4.1 G1的内存划分和主要收集过程 95
5.4.2 G1的新生代GC 96
5.4.3 G1的并发标记周期 97
5.4.4 混合回收 100
5.4.5 必要时的Full GC 102
5.4.6 G1的日志 102
5.4.7 G1相关的参数 106
5.5 回眸:有关对象内存分配和回收的一些细节问题 106
5.5.1 禁用System.gc() 107
5.5.2 System.gc()使用并发回收 107
5.5.3 并行GC前额外触发的新生代GC 109
5.5.4 对象何时进入老年代 109
5.5.5 在TLAB上分配对象 117
5.5.6 finalize()函数对垃圾回收的影响 120
5.6 温故又知新:常用的GC参数 125
5.7 动手才是真英雄:垃圾回收器对Tomcat性能影响的实验 127
5.7.1 配置实验环境 127
5.7.2 配置性能测试工具JMeter 128
5.7.3 配置Web应用服务器Tomcat 131
5.7.4 实战案例1—初试串行回收器 133
5.7.5 实战案例2—扩大堆以提升系统性能 133
5.7.6 实战案例3—调整初始堆大小 134
5.7.7 实战案例4—使用ParrellOldGC回收器 135
5.7.8 实战案例5—使用较小堆提高GC压力 135
5.7.9 实战案例6—测试ParallelOldGC的表现 135
5.7.10 实战案例7—测试ParNew回收器的表现 136
5.7.11 实战案例8—测试JDK 1.8的表现 136
5.7.12 实战案例9—使用高版本虚拟机提升性能 137
5.8 小结 137
第6章 性能监控工具 138
6.1 有我更高效:Linux下的性能监控工具 139
6.1.1 显示系统整体资源使用情况—top命令 139
6.1.2 监控内存和CPU—vmstat命令 140
6.1.3 监控I/O—iostat命令 142
6.1.4 多功能诊断器—pidstat工具 143
6.2 用我更高效:Windows下的性能监控工具 148
6.2.1 任务管理器 148
6.2.2 perfmon性能监控工具 150
6.2.3 Process Explorer进程管理工具 153
6.2.4 pslist命令—Windows下也有命令行工具 155
6.3 外科手术刀:JDK性能监控工具 157
6.3.1 查看Java进程—jps命令 158
6.3.2 查看虚拟机运行时信息—jstat命令 159
6.3.3 查看虚拟机参数—jinfo命令 162
6.3.4 导出堆到文件—jmap命令 163
6.3.5 JDK自带的堆分析工具—jhat命令 165
6.3.6 查看线程堆栈—jstack命令 168
6.3.7 远程主机信息收集—jstatd命令 171
6.3.8 多功能命令行—jcmd命令 173
6.3.9 性能统计工具—hprof 175
6.3.10 扩展jps命令 178
6.4 我是你的眼:图形化虚拟机监控工具JConsole 178
6.4.1 JConsole连接Java程序 179
6.4.2 Java程序概况 180
6.4.3 内存监控 180
6.4.4 线程监控 181
6.4.5 类加载情况 183
6.4.6 虚拟机信息 183
6.5 一目了然:可视化性能监控工具Visual VM 184
6.5.1 Visual VM连接应用程序 185
6.5.2 监控应用程序概况 186
6.5.3 Thread Dump和分析 187
6.5.4 性能分析 188
6.5.5 内存快照分析 190
6.5.6 BTrace介绍 191
6.6 来自JRockit的礼物:虚拟机诊断工具Mission Control 199
6.6.1 MBean服务器 199
6.6.2 飞行记录器(Flight Recorder) 201
6.7 小结 204
第7章 分析Java堆 205
7.1 对症才能下药:找到内存溢出的原因 206
7.1.1 堆溢出 206
7.1.2 直接内存溢出 206
7.1.3 过多线程导致OOM 208
7.1.4 永久区溢出 210
7.1.5 GC效率低下引起的OOM 211
7.2 无处不在的字符串:String在虚拟机中的实现 211
7.2.1 String对象的特点 211
7.2.2 有关String的内存泄漏 213
7.2.3 有关String常量池的位置 216
7.3 虚拟机也有内窥镜:使用MAT分析Java堆 218
7.3.1 初识MAT 218
7.3.2 浅堆和深堆 221
7.3.3 MAT堆分析案例解析 222
7.3.4 支配树(Dominator Tree) 226
7.3.5 Tomcat堆溢出分析 227
7.4 筛选堆对象:MAT对OQL的支持 231
7.4.1 Select子句 231
7.4.2 From子句 233
7.4.3 Where子句 235
7.4.4 内置对象与方法 235
7.5 更精彩的查找:Visual VM对OQL的支持 240
7.5.1 Visual VM的OQL基本语法 240
7.5.2 内置heap对象 241
7.5.3 对象函数 243
7.5.4 集合/统计函数 247
7.5.5 程序化OQL分析Tomcat堆 253
7.6 小结 256
第8章 锁与并发 257
8.1 安全就是锁存在的理由:锁的基本概念和实现 258
8.1.1 理解线程安全 258
8.1.2 对象头和锁 260
8.2 避免残酷的竞争:锁在Java虚拟机中的实现和优化 261
8.2.1 偏向锁 261
8.2.2 轻量级锁 263
8.2.3 锁膨胀 264
8.2.4 自旋锁 265
8.2.5 锁消除 265
8.3 应对残酷的竞争:锁在应用层的优化思路 267
8.3.1 减少锁持有时间 267
8.3.2 减小锁粒度 268
8.3.3 锁分离 270
8.3.4 锁粗化 272
8.4 无招胜有招:无锁 274
8.4.1 理解CAS 274
8.4.2 原子操作 275
8.4.3 新宠儿LongAdder 278
8.5 将随机变为可控:理解Java内存模型 281
8.5.1 原子性 281
8.5.2 有序性 283
8.5.3 可见性 285
8.5.4 Happens-Before原则 287
8.6 小结 287
第9章 Class文件结构 288
9.1 不仅跨平台,还能跨语言:语言无关性 288
9.2 虚拟机的基石:Class文件 290
9.2.1 Class文件的标志—魔数 291
9.2.2 Class文件的版本 293
9.2.3 存放所有常数—常量池 294
9.2.4 Class的访问标记(Access Flag) 301
9.2.5 当前类、父类和接口 302
9.2.6 Class文件的字段 303
9.2.7 Class文件的方法基本结构 305
9.2.8 方法的执行主体—Code属性 307
9.2.9 记录行号—LineNumberTable属性 308
9.2.10 保存局部变量和参数—LocalVariableTable属性 309
9.2.11 加快字节码校验—StackMapTable属性 309
9.2.12 Code属性总结 314
9.2.13 抛出异常—Exceptions属性 315
9.2.14 用实例分析Class的方法结构 316
9.2.15 我来自哪里—SourceFile属性 319
9.2.16 强大的动态调用—BootstrapMethods属性 320
9.2.17 内部类—InnerClasses属性 321
9.2.18 将要废弃的通知—Deprecated属性 322
9.2.19 Class文件总结 323
9.3 操作字节码:走进ASM 323
9.3.1 ASM体系结构 323
9.3.2 ASM之Hello World 325
9.4 小结 326
第10章 Class装载系统 327
10.1 来
Java是目前应用最广泛的软件开发平台之一。随着Java及Java社区的不断壮大,Java也早已不再是简简单单的一门计算机语言了,它更是一个平台、一种文化、一个社区。
作为一个平台,Java虚拟机扮演着举足轻重的作用。除了Java语言,任何一种能够被编译成字节码的计算机语言都属于Java这个平台。Groovy、Scala、JRuby、Kotlin等都是Java平台的一部分,它们依赖于Java虚拟机,同时,Java平台也因为它们变得更加丰富多彩。
作为一种文化,Java几乎成了“开源”的代名词。在Java程序中,有着数不清的开源软件和框架,如Tomcat、Struts、Hibernate、Spring等。就连JDK和JVM自身也有不少开源的实现,如OpenJDK、Harmony。可以说,“共享”的精神在Java世界里体现得淋漓尽致。
作为一个社区,Java拥有无数的开发人员,有数不清的论坛和资料。从桌面应用软件、嵌入式开发到企业级应用、后台服务器、中间件,都可以看到Java的身影。其应用形式之复杂、参与人数之众多也令人咋舌。可以说,Java社区俨然已经成为一个良好而庞大的生态系统,而本书,将主要介绍这个生态系统的核心——Java虚拟机。
第2版的重点修订
作者希望本书第2版的内容能够涵盖JDK 7~JDK 10,所以特做如下修订:
?JDK 10 源码环境的下载与搭建。
?JDK 10 JVM的调试方法介绍。
?JDK 10 运行参数的演变。
?JDK 10用G1垃圾回收器替代CMS垃圾回收器,成为默认的垃圾回收器。
?JDK 10调试工具的更新,废除功能类似的调试工具,重点推荐使用Visual VM。
本书的体系结构
本书立足于实际开发,又不缺乏理论介绍,力求通俗易懂、循序渐进。全书共分为11章。
第1章综述,介绍了Java虚拟机的概念、定义,讲解了Java语言规范和Java虚拟机规范,最后还介绍了OpenJDK的调试方法。
第2章介绍了Java虚拟机的总体架构,说明了堆、栈、方法区等内存空间的作用和彼此之间的联系。
第3章介绍了Java虚拟机的常用配置参数,重点对垃圾回收跟踪参数、内存配置参数做了详细介绍,并给出了案例说明。
第4章从理论层面介绍了垃圾回收的算法,如引用计数、标记清除、标记压缩、复制算法等。本章是第5章的理论基础。
第5章基于垃圾回收的理论知识,进一步详细介绍了Java虚拟机中实际使用的各种垃圾回收器,包括串行回收器、并行回收器、CMS、G1等。
第6章介绍了Java虚拟机的性能监控和故障诊断工具,考虑到实用性,也介绍了系统级性能监控工具的使用,两者结合,可以更好地帮助读者处理实际问题。
第7章详细介绍了对Java堆的分析方法和案例,主要讲解了MAT和Visual VM两款工具的使用,以及各自OQL的编写方式。
第8章介绍了Java虚拟机对多线程,尤其是对锁的支持。本章不仅介绍了虚拟机内部锁的实现、优化机制,也给出了Java语言层面的一些锁优化思路,最后还介绍了无锁的并行控制方法。
第9章介绍了Java虚拟机的核心——Class文件结构,Class文件作为Java虚拟机的基石,有着举足轻重的作用,对深入理解Java虚拟机有着不可忽视的作用。
第10章介绍了Java虚拟机中类的装载系统,其中着重介绍了Java虚拟机中ClassLoader的实现及设计模式。
第11章介绍了Java虚拟机的执行系统和字节码。为了帮助读者更快、更好地理解Java字节码,本章对字节码进行了分类讲解,并且理论联系实际,给出了通过ASM框架进行字节码注入的案例。
本书特色
本书的主要特点有:
?结构清晰。本书采用从整体到局部的视角,首先,第1、2章介绍了Java虚拟机的整体概况和结构。接着步步为营,每一章节对应单独的知识点,力求展示虚拟机的全貌。
?理论结合实战。本书不甘心于简单地枚举理论知识,在每一个理论背后,都给出了演示示例供读者参考,帮助读者更好地消化这些理论。比如,在对Class文件结构和字节码的介绍中,不仅仅简单地给出了理论说明,更是使用ASM框架将这些理论应用于实践,尽可能地做到理论与实践结合。
?专注专业。本书着眼于Java虚拟机,对Java虚拟机的原理和实践做了丰富的介绍,包括但不限于体系结构、虚拟机的调试方式、常用参数、垃圾回收系统、Class文件结构、执行系统等,力求从多角度更专业地对Java虚拟机进行探讨。
?通俗易懂。本书依然服务于广大虚拟机初学者,尽量避免采用过于理论化的描述方式,简单的白话文风格贯穿全书,尽量使读者在阅读过程中少盲点、无盲点。
?技术全面。纵横Windows和Linux双系统下的性能诊断、涉及32位系统和64位系统的优化比较、贯穿从JDK 1.5到JDK 10的优化演进。
适合阅读人群
虽然本书讲解力求通俗,但要通读本书并取得良好的学习效果,要求读者需要具备基本的Java知识或者一定的编程经验。因此,本书适合以下读者:
?拥有一定开发经验的Java平台开发人员(Java、Scala、JRuby等)。
?软件设计师、架构师。
?系统调优人员。
?有一定的Java编程基础并希望进一步理解Java的程序员。
?虚拟机爱好者,JVM实践者。
本书的约定
本书在叙述过程中,有如下约定:
?本书中所述的JDK 1.5、JDK 1.6、JDK 1.7、JDK 1.8、JDK 1.9、JDK 1.10等同于JDK 5、JDK 6、JDK 7、JDK 8、JDK 9、JDK 10。
?如无特殊说明,Java虚拟机均指HotSpot虚拟机。
?如无特殊说明,本书的程序、示例均在JDK 7~JDK 10环境中运行。
联系作者
本书的写作过程远比想象的艰辛,为了让全书能够更清楚、更正确地表达和论述,我经历了好多个不眠之夜,即使现在回想起来,也忍不住会打个寒战。由于写作水平的限制,书中难免会有不妥之处,望读者谅解。
为此,如果读者有任何疑问或者建议,非常欢迎大家加入QQ群254693571,一起探讨学习中的困难、分享学习的经验,我期待与大家一起交流、共同进步。同时,也希望大家可以关注我的博客http://www.uucode.net/。
感谢
这本书能够面世,是因为得到了众人的支持。首先,要感谢我的妻子,她始终不辞辛劳,毫无怨言地对我照顾有加,才让我得以腾出大量时间,并可以安心工作。其次,要感谢编辑为我一次又一次地审稿改错、批评指正,才让本书逐步完善。最后,感谢我的母亲30年如一日对我的体贴和关心。
特别感谢网友千马奕在JDK 1.9、JDK1.10下对本书所做的测试和修订。
读者服务
轻松注册成为博文视点社区用户(www.broadview.com.cn),您即可享受以下服务:
?下载资源:本书如提供示例代码及资源文件,均可在 下载资源 处下载。
?提交勘误:您对书中内容的修改意见可在 提交勘误 处提交,若被采纳,将获赠博文视点社区积分(在您购买电子书时,积分可用来抵扣相应金额)。
?与作者交流:在页面下方 读者评论 处留下您的疑问或观点,与作者和其他读者一同学习交流。
页面入口:http://www.broadview.com.cn/36774
★ 个人认为比老外写的那本要通俗易懂,而且更贴近中国程序员的需要,对jvm的概况,以后为啥要了解jvm这块说的不错,整体而言是本好书。
★ 之前在图书馆借阅过,内容丰富,实践性强,再买一本以备温习之用。
★ 讲的不错,先讲原理,由浅入深,由理论到实践。
★ 内容充实,容易理解,知识点详细。
★ 适合初级JVM初学者学习,大部分是实战经验,不错的一本书,*物流一如既往的快。
★ 葛一鸣 写的书、基本上 都受益良多、感谢。
★ 和虚拟机相关的不错的一本书,纸张不错,内容也比较实用,很满意
★ 相对偏实践,和深入理解JVM一起看。
……
3.4 Client和Server二选一:虚拟机的工作模式
目前Java虚拟机支持Client和Server两种运行模式。使用参数-client可以指定使用Client模式,使用参数-server可以指定使用Server模式。在默认情况下,虚拟机会根据当前计算机系统环境自动选择运行模式。使用-version参数可以查看当前模式,如下所示:
./java -version
java version “1.7.0_40”
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode, sharing)
使用-server参数后,就可以得到如下输出:
./java -server -version
java version “1.7.0_40”
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Server VM (build 24.0-b56, mixed mode)
与Client模式相比,Server模式的启动比较慢,因为Server模式会尝试收集更多的系统性能信息,使用更复杂的优化算法对程序进行优化。因此,当系统完全启动并进入运行稳定期后,Server模式的执行速度会远远快于Client模式。所以,对于后台长期运行的系统来说,使用-server参数启动对系统的整体性能可以有不小的帮助。但对于用户界面程序而言,运行时间不长,又追求启动速度,Client模式也是不错的选择。
从发展趋势上看,未来64位系统必然会逐步取代32位系统,而在64位系统中虚拟机更倾向于使用Server模式。
虚拟机在Server模式和Client模式下的各种参数可能会有很大的不同,读者如果需要查看给定参数的默认值,可以使用-XX: PrintFlagsFinal参数。这里以JIT编译阈值和最大堆为例,展示Client模式和Server模式的区别。
对于Client模式,参数如下:
./java -XX: PrintFlagsFinal -client -version |grep -E ‘ CompileThreshold| MaxHeapSize’
intx CompileThreshold = 1500{pd product}
uintx MaxHeapSize:= 268435456{product}
java version “1.7.0_40”
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode, sharing)
对于Server模式,参数如下:
./java -XX: PrintFlagsFinal -server -version |grep -E ‘ CompileThreshold| MaxHeapSize’
intx CompileThreshold = 10000 {pd product}
uintx MaxHeapSize:= 1073741824 {product}
java version “1.7.0_40”
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Server VM (build 24.0-b56, mixed mode)
可以看到,在Client模式下,CompileThreshold的默认值为1500,即函数被调用1500次后,会进行JIT编译(有关JIT编译的更多细节请参阅第11章)。而在Server模式下,这个数值为10000。因此,在Server模式下系统更有可能解释执行。而一旦进行编译,Server模式的优化效果会好于Client模式。对于系统最大堆,在Client模式下为约256MB,而在Server模式下约为1GB。至于其他参数,读者可以使用类似的方式进行比较。
3.5 小结
本章主要介绍了一些常用的Java虚拟机参数,如垃圾回收跟踪参数、类加载跟踪参数等。同时也详细介绍了堆空间的配置方法及方法区、Java栈和直接内存配置。此外,还介绍了系统发生内存溢出后的信息获取和补救方法。最后,简要介绍了虚拟机的Server和Client运行模式。
评论
还没有评论。