本书以Java性能调优为主线,系统地阐述了与Java性能优化相关的知识与技巧。本书共6章,先后从软件设计、软件编码、JVM调优及程序故障排除等方面介绍针对Java程序的优化方法。第1章介绍性能的基本概念、木桶原理与Amdahl定律、系统调优的过程和注意事项;第2章从设计层面介绍与性能相关的设计模式及常用优化组件;第3章从代码层面介绍如何编写高性能的Java程序;第4章介绍并进行开发和如何通过多线程提高系统性能;第5章立足于JVM虚拟机层面,介绍如何通过设置合理的JVM参数提升Java程序的性能;第6章为工具篇,介绍了获取和监控程序或系统性能指标的各种工具,包括相关的故障排查工具。本书适合所有Java程序员、软件设计师、架构师及软件开发爱好者,对于有一定经验的Java工程师,本书更能帮助他突破技术瓶颈,深入Java内核开发!
前言
第1章 Java性能调优概述1
1.1 性能概述1
1.1.1 看懂程序的性能1
1.1.2 性能的参考指标2
1.1.3 木桶原理与性能瓶颈2
1.1.4 Amdahl定律3
1.2 性能调优的层次5
1.2.1 设计调优5
1.2.2 代码调优6
1.2.3 JVM调优6
1.2.4 数据库调优6
1.2.5 操作系统调优7
1.3 基本调优策略和手段7
1.3.1 优化的一般步骤8
1.3.2 系统优化的注意事项8
1.4 小结9
第2章 设计优化10
2.1 善用设计模式10
2.1.1 单例模式10
2.1.2 代理模式15
2.1.3 享元模式24
2.1.4 装饰者模式28
2.1.5 观察者模式34
2.1.6 值对象模式38
2.1.7 业务代理模式41
2.2 常用的优化组件和方法44
2.2.1 缓冲44
2.2.2 缓存47
2.2.3 对象复用——池51
2.2.4 并行替代串行58
2.2.5 负载均衡58
2.2.6 时间换空间63
2.2.7 空间换时间64
2.3 小结66
第3章 Java程序优化67
3.1 字符串优化处理67
3.1.1 String对象及其特点67
3.1.2 substring()方法的内存泄漏69
3.1.3 字符串分割和查找72
3.1.4 StringBuffer和StringBuilder76
3.1.5 CompactStrings优化字符串存储80
3.2 核心数据结构81
3.2.1 List接口81
3.2.2 Map接口88
3.2.3 Set接口100
3.2.4 优化集合访问代码101
3.2.5 RandomAccess接口103
3.3 使用NIO提升性能105
3.3.1 NIO中的Buffer类族和Channel106
3.3.2 Buffer的基本原理107
3.3.3 Buffer的相关操作109
3.3.4 MappedByteBuffer性能评估116
3.3.5 直接访问内存119
3.4 引用类型121
3.4.1 强引用121
3.4.2 软引用122
3.4.3 弱引用123
3.4.4 虚引用124
3.4.5 WeakHashMap类及其实现127
3.5 性能测试工具JMH129
3.5.1 JMH之Hello World130
3.5.2 JMH之指定测量模式131
3.5.3 JMH之对象作用域134
3.5.4 JMH之代码消除135
3.6 有助于改善性能的技巧137
3.6.1 使用局部变量137
3.6.2 位运算代替乘除法138
3.6.3 替换switch139
3.6.4 一维数组代替二维数组141
3.6.5 提取表达式142
3.6.6 展开循环143
3.6.7 布尔运算代替位运算144
3.6.8 使用arrayCopy()145
3.6.9 使用Buffer进行I/O操作147
3.6.10 使用clone()代替new149
3.6.11 慎用Java函数式编程151
3.7 小结152
第4章 并行程序开发及优化153
4.1 并行程序设计模式153
4.1.1 Future模式153
4.1.2 Master-Worker模式161
4.1.3 Guarded Suspension模式165
4.1.4 不变模式172
4.1.5 生产者-消费者模式174
4.2 JDK多任务执行框架178
4.2.1 无限制线程的缺陷178
4.2.2 简单的线程池实现179
4.2.3 Executor框架183
4.2.4 自定义线程池185
4.2.5 优化线程池大小189
4.2.6 扩展ThreadPoolExecutor189
4.3 JDK并发数据结构191
4.3.1 并发List191
4.3.2 并发Set193
4.3.3 并发Map194
4.3.4 并发Queue195
4.3.5 并发Deque197
4.4 并发控制方法199
4.4.1 Java内存模型与volatile199
4.4.2 同步关键字synchronized203
4.4.3 重入锁205
4.4.4 读写锁207
4.4.5 读写锁的改进:StampedLock209
4.4.6 Condition对象210
4.4.7 信号量212
4.4.8 线程局部变量ThreadLocal214
4.5 锁的性能和优化215
4.5.1 线程的开销215
4.5.2 避免死锁215
4.5.3 减少锁持有时间219
4.5.4 减小锁粒度220
4.5.5 读写分离锁来替换独占锁221
4.5.6 锁分离222
4.5.7 重入锁和内部锁224
4.5.8 锁粗化224
4.5.9 自旋锁226
4.5.10 锁消除226
4.5.11 锁偏向227
4.6 无锁的并行计算228
4.6.1 非阻塞的同步/无锁228
4.6.2 原子操作228
4.6.3 Amino框架简介231
4.6.4 Amino集合231
4.6.5 Amino树236
4.6.6 Amino图237
4.6.7 Amino简单调度模式238
4.7 协程240
4.7.1 协程的概念240
4.7.2 Kilim框架简介241
4.7.3 Task及其状态242
4.7.4 Fiber及其状态242
4.7.5 Kilim开发环境配置243
4.7.6 Kilim之Hello World244
4.7.7 多任务通信246
4.7.8 Kilim实例及性能评估247
4.8 小结250
第5章 JVM调优251
5.1 Java虚拟机内存模型251
5.1.1 程序计数器251
5.1.2 Java虚拟机栈252
5.1.3 本地方法栈258
5.1.4 Java堆258
5.1.5 方法区260
5.2 JVM内存分配参数263
5.2.1 设置最大堆内存264
5.2.2 设置最小堆内存264
5.2.3 设置新生代266
5.2.4 设置持久代266
5.2.5 设置线程栈267
5.2.6 堆的比例分配269
5.2.7 堆分配参数总结270
5.3 垃圾收集基础271
5.3.1 垃圾收集的作用272
5.3.2 垃圾回收算法与思想272
5.3.3 垃圾回收器的类型277
5.3.4 评价GC策略的指标278
5.3.5 新生代串行回收器278
5.3.6 老年代串行回收器279
5.3.7 并行回收器280
5.3.8 新生代并行回收器281
5.3.9 老年代并行回收器282
5.3.10 CMS回收器282
5.3.11 G1回收器285
5.3.12 Stop the World案例286
5.3.13 垃圾回收器对系统性能的影响288
5.3.14 GC操作相关参数总结289
5.4 常用调优案例和方法291
5.4.1 将新对象预留在新生代291
5.4.2 大对象进入老年代294
5.4.3 设置对象进入老年代的年龄296
5.4.4 稳定与振荡的堆大小296
5.4.5 吞吐量优先案例298
5.4.6 使用大页案例298
5.4.7 降低停顿案例299
5.5 实用JVM参数299
5.5.1 JIT编译参数299
5.5.2 堆快照301
5.5.3 错误处理302
5.5.4 获取GC信息302
5.5.5 类和对象跟踪304
5.5.6 控制GC305
5.5.7 选择类校验器305
5.5.8 Solaris下的线程控制306
5.5.9 使用大页306
5.5.10 压缩指针306
5.6 JVM调优实战306
5.6.1 Tomcat简介与启动加速307
5.6.2 Web应用程序简介309
5.6.3 JMeter简介与使用310
5.6.4 调优前Web应用运行状况313
5.6.5 调优过程314
5.7 小结315
第6章 Java性能调优工具316
6.1 Linux命令行工具316
6.1.1 top命令316
6.1.2 sar命令318
6.1.3 vmstat命令319
6.1.4 iostat命令321
6.1.5 pidstat工具322
6.2 Windows工具326
6.2.1 任务管理器326
6.2.2 perfmon性能监控工具328
6.2.3 Process Explorer工具331
6.2.4 pslist命令行333
6.3 JDK命令行工具334
6.3.1 jps命令335
6.3.2 jstat命令336
6.3.3 jinfo命令339
6.3.4 jmap命令340
6.3.5 jhat命令341
6.3.6 jstack命令343
6.3.7 jstatd命令346
6.3.8 hprof工具347
6.3.9 jcmd命令349
6.4 JConsole工具350
6.4.1 JConsole连接Java程序350
6.4.2 Java程序概况351
6.4.3 内存监控352
6.4.4 线程监控352
6.4.5 类加载情况354
6.4.6 虚拟机信息354
6.4.7 MBean管理355
6.4.8 使用插件356
6.5 Visual VM多合一工具357
6.5.1 Visual VM连接应用程序358
6.5.2 监控应用程序概况359
6.5.3 Thread Dump和分析361
6.5.4 性能分析362
6.5.5 快照365
6.5.6 内存快照分析365
6.5.7 MBean管理功能367
6.5.8 TDA的使用367
6.5.9 BTrace简介368
6.6 Visual VM对OQL的支持374
6.6.1 Visual VM的OQL基本语法374
6.6.2 内置heap对象375
6.6.3 对象函数376
6.6.4 集合/统计函数380
6.6.5 程序化OQL384
6.7 MAT内存分析工具386
6.7.1 初识MAT386
6.7.2 浅堆和深堆389
6.7.3 支配树392
6.7.4 垃圾回收根394
6.7.5 内存泄漏检测395
6.7.6 最大对象报告396
6.7.7 查找支配者396
6.7.8 线程分析397
6.7.9 集合使用情况分析398
6.7.10 扩展MAT399
6.8 MAT对OQL的支持403
6.8.1 Select子句404
6.8.2 From子句406
6.8.3 Where子句407
6.8.4 内置对象与方法408
6.9 来自JRockit的礼物——JMC411
6.9.1 得到JFR文件412
6.9.2 Java程序的整体运行情况413
6.9.3 CPU分析413
6.9.4 内存分析414
6.9.5 I/O分析416
6.10 小结418