深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 3 版)- 周志明
深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 3 版)- 周志明
程序员朱永胜元数据
[!abstract] 深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 3 版)
- 书名:深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 3 版)
- 作者:周志明
- 简介:内容介绍
这是一部从工作原理和工程实践两个维度深入剖析 JVM 的著作,是计算机领域公认的经典,繁体版在台湾也颇受欢迎。
自 2011 年上市以来,前两个版本累计印刷 36 次,销量超过 30 万册,两家主要网络书店的评论近 90000 条,内容上近乎零差评,是原创计算机图书领域不可逾越的丰碑。
第 3 版在第 2 版的基础上做了重大修订,内容更丰富、实战性更强:根据新版 JDK 对内容进行了全方位的修订和升级,围绕新技术和生产实践新增逾 10 万字,包含近 50% 的全新内容,并对第 2 版中含糊、瑕疵和错误内容进行了修正。
全书一共 13 章,分为五大部分:
第壹部分(第 1 章)走近 Java
系统介绍了 Java 的技术体系、发展历程、虚拟机家族,以及动手编译 JDK,了解这部分内容能对学习 JVM 提供良好的指引。
第二部分(第 25 章)自动内存管理9 章)虚拟机执行子系统
详细讲解了 Java 的内存区域与内存溢出、垃圾收集器与内存分配策略、虚拟机性能监控与故障排除等与自动内存管理相关的内容,以及 10 余个经典的性能优化案例和优化方法;
第三部分(第 6
深入分析了虚拟机执行子系统,包括类文件结构、虚拟机类加载机制、虚拟机字节码执行引擎,以及多个类加载及其执行子系统的实战案例;
第四部分(第 1011 章)程序编译与代码优化13 章)高效并发
详细讲解了程序的前、后端编译与优化,包括前端的易用性优化措施,如泛型、主动装箱拆箱、条件编译等的内容的深入分析;以及后端的性能优化措施,如虚拟机的热点探测方法、HotSpot 的即时编译器、提前编译器,以及各种常见的编译期优化技术;
第五部分(第 12
主要讲解了 Java 实现高并发的原理,包括 Java 的内存模型、线程与协程,以及线程安全和锁优化。
全书以实战为导向,通过大量与实际生产环境相结合的案例分析和展示了解决各种 Java 技术难题的方案和技巧。- 出版时间:2021-05-16 00:00:00
- ISBN:9787111641247
- 分类:计算机 - 编程设计
- 出版社:机械工业出版社
- PC 地址:https://weread.qq.com/web/reader/cf1320d071a1a78ecf19254
高亮划线
1.1 概述
📌 它摆脱了硬件平台的束缚,实现了 “ 一次编写,到处运行 “ 的理想;它提供了一种相对安全的内存管理和访问机制,避免了绝大部分内存泄漏和指针越界问题;它实现了热点代码检测和运行时编译及优化,这使得 Java 应用能随着运行时间的增长而获得更高的性能;它有一套完善的应用程序接口,还有无数来自商业机构和开源社区的第三方类库来帮助用户实现各种各样的功能……Java 带来的这些好处,让软件的开发效率得到了极大的提升。
⏱ 2023-06-12 21:40:34 ^27371406-6-1056-1254
📌 从更严格的角度来看,Graal VM 才是真正意义上与物理计算机相对应的高级语言虚拟机,理由是它与物理硬件的指令集一样,做到了只与机器特性相关而不与某种高级语言特性相关
⏱ 2023-06-13 13:56:36 ^27371406-10-2451-2534
📌 HotSpot 虚拟机中含有两个即时编译器,分别是编译耗时短但输出代码优化程度较低的客户端编译器(简称为 C1)以及编译耗时长但输出代码优化质量也更高的服务端编译器(简称为 C2)
⏱ 2023-06-13 13:55:54 ^27371406-10-3820-3907
📌 自 JDK 10 起,HotSpot 中又加入了一个全新的即时编译器:Graal 编译器
⏱ 2023-06-13 13:56:52 ^27371406-10-4001-4041
📌 Substrate VM 带来的好处是能显著降低内存占用及启动时间
⏱ 2023-06-13 14:01:37 ^27371406-10-7074-7106
📌 现在的 Java 做并发处理的最小调度单位是线程,Java 线程的调度是直接由操作系统内核提供的(这方面的内容可见本书第 12 章),会有核心态、用户态的切换开销。
⏱ 2023-06-13 17:00:05 ^27371406-10-11817-11894
📌 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器
⏱ 2020-06-11 10:10:53 ^27371406-15-896-961
📌 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
⏱ 2020-06-11 10:17:13 ^27371406-15-1129-1167
📌 为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器
⏱ 2020-06-11 10:11:08 ^27371406-15-1335-1372
📌 正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址
⏱ 2020-06-11 10:21:53 ^27371406-15-1445-1485
📌 正在执行的是本地(Native)方法,这个计数器值则应为空(Undefined)
⏱ 2020-06-11 10:21:58 ^27371406-15-1488-1528
📌 Java 虚拟机栈(Java Virtual Machine Stack)也是线程私有的,它的生命周期与线程相同
⏱ 2020-06-11 10:09:55 ^27371406-15-1686-1741
📌 每个方法被执行的时候,Java 虚拟机都会同步创建一个栈帧 [插图](Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息
⏱ 2020-06-11 10:09:24 ^27371406-15-1766-1937
📌 局部变量表存放了编译期可知的各种 Java 虚拟机基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和 returnAddress 类型(指向了一条字节码指令的地址)
⏱ 2020-06-11 10:28:59 ^27371406-15-2250-2434
📌 局部变量表所需的内存空间在编译期间完成分配
⏱ 2020-06-11 10:32:33 ^27371406-15-2544-2565
📌 在方法运行期间不会改变局部变量表的大小
⏱ 2020-06-11 10:32:48 ^27371406-15-2603-2622
📌 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常;如果 Java 虚拟机栈容量可以动态扩展 [插图],当栈扩展时无法申请到足够的内存会抛出 OutOfMemoryError 异常
⏱ 2020-06-11 10:36:02 ^27371406-15-2779-3129
📌 Java 堆是被所有线程共享的一块内存区域
⏱ 2020-06-11 10:44:35 ^27371406-15-3682-3702
📌 此内存区域的唯一目的就是存放对象实例
⏱ 2020-06-11 10:44:43 ^27371406-15-3713-3731
📌 方法区(Method Area)与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据
⏱ 2020-06-11 10:49:21 ^27371406-15-5741-5821
📌 运行时常量池(Runtime Constant Pool)是方法区的一部分
⏱ 2020-06-11 10:55:35 ^27371406-15-7412-7449
📌 本机直接内存的分配不会受到 Java 堆大小的限制,
⏱ 2020-06-11 10:59:09 ^27371406-15-8612-8636
📌 单纯的引用计数就很难解决对象之间相互循环引用的问题。
⏱ 2020-06-13 09:54:49 ^27371406-21-1046-1072
📌 G1 的记忆集在存储结构的本质上是一种哈希表,Key 是别的 Region 的起始地址,Value 是一个集合,里面存储的元素是卡表的索引号
⏱ 2020-06-14 12:55:35 ^27371406-24-17803-17868
📌 衰减均值
⏱ 2020-06-14 13:04:10 ^27371406-24-18673-18677
📌 从 G1 开始,最先进的垃圾收集器的设计导向都不约而同地变为追求能够应付应用的内存分配速率(Allocation Rate),而不追求一次把整个 Java 堆全部清理干净
⏱ 2020-06-14 15:46:42 ^27371406-24-21110-21191
3.6 低延迟垃圾收集器
📌 衡量垃圾收集器的三项最重要的指标是:内存占用(Footprint)、吞吐量(Throughput)和延迟(Latency
⏱ 2020-06-14 15:55:33 ^27371406-25-564-618
📌 ZGC 收集器是一款基于 Region 内存布局的,(暂时)不设分代的,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记 - 整理算法的,以低延迟为首要目标的一款垃圾收集器
⏱ 2020-06-14 16:27:39 ^27371406-25-13877-13964
📌 直接将少量额外的信息存储在指针上的技术
⏱ 2020-06-14 17:08:39 ^27371406-25-15792-15811
📌 染色指针可以使得一旦某个 Region 的存活对象被移走之后,这个 Region 立即就能够被释放和重用掉,而不必等待整个堆中所有指向该 Region 的引用都被修正后才能清理
⏱ 2020-06-14 17:14:31 ^27371406-25-17515-17597
📌 染色指针可以大幅减少在垃圾收集过程中内存屏障的使用数量
⏱ 2020-06-14 17:14:46 ^27371406-25-17828-17855
📌 实际上,到目前为止 ZGC 都并未使用任何写屏障,只使用了读屏障(一部分是染色指针的功劳,一部分是 ZGC 现在还不支持分代收集,天然就没有跨代引用的问题
⏱ 2020-06-14 17:18:07 ^27371406-25-17922-17995
📌 染色指针可以作为一种可扩展的存储结构用来记录更多与对象标记、重定位过程相关的数据,以便日后进一步提高性能
⏱ 2020-06-14 17:18:44 ^27371406-25-18101-18153
📌 染色指针技术
⏱ 2020-06-14 17:06:42 ^27371406-25-15039-15045
6.3 Class 类文件的结构
📌 无符号数属于基本的数据类型,以 u1、u2、u4、u8 来分别代表 1 个字节、2 个字节、4 个字节和 8 个字节的无符号数
⏱ 2020-06-14 20:20:02 ^27371406-43-1935-1990
📌 表是由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以 “_info” 结尾
⏱ 2020-06-14 20:19:49 ^27371406-43-2060-2117
📌 当平台及应用程序类加载器收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块中,如果可以找到这样的归属关系,就要优先委派给负责那个模块的加载器完成加载
⏱ 2020-06-15 15:02:56 ^27371406-53-7288-7377
📌 所有依赖静态类型来决定方法执行版本的分派动作,都称为静态分派
⏱ 2020-06-15 15:26:50 ^27371406-58-6277-6307
📌 如今(直至本书编写的 Java 12 和预览版的 Java 13)的 Java 语言是一门静态多分派、动态单分派的语言
⏱ 2020-06-15 15:35:32 ^27371406-58-18054-18108
读书笔记
3.6 低延迟垃圾收集器
划线评论
📌 然 ^280435523-7i6h8iDwA
- 💭。。。优秀
- ⏱ 2020-06-14 17:18:20
本书评论
书评 No.1
^280435523-7IWmYMADv
⏱ 2023-06-13 17:07:28