深入理解Java虚拟机
周志明系统讲解Java虚拟机内部工作原理,涵盖内存管理、垃圾回收、类加载、字节码执行等核心主题,是Java开发者深入理解JVM的必读经典。
本书速读
JVM内存模型全景
Java虚拟机内存管理是理解JVM运行机制的核心基石,掌握内存结构是成为高级Java开发者的必经之路。
堆内存:Java堆是所有线程共享的内存区域,对象实例几乎都在这里分配,是垃圾收集器管理的主要区域,分为新生代和老年代两部分。
方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,在HotSpot JVM中表现为永久代或元空间。
虚拟机栈:每个方法从调用到执行完成的过程都对应着一个栈帧在虚拟机栈中入栈到出栈的过程,包含局部变量表、操作数栈、动态链接和方法出口等信息。
本地方法栈:为Native方法服务,与虚拟机栈发挥的作用类似,区别仅在于虚拟机栈为Java方法服务而本地方法栈为Native方法服务。
程序计数器:当前线程所执行的字节码的行号指示器,是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
垃圾回收机制深度解析
垃圾回收是JVM最重要的特性之一,自动内存管理极大地降低了Java程序员的开发负担。
如何判断对象已死:引用计数算法和可达性分析算法是两种主要的判断方式,HotSpot JVM采用可达性分析算法,通过GC Roots作为起始点搜索引用链。
四种引用类型:强引用、软引用、弱引用和虚引用,它们具有不同的垃圾回收行为,合理使用可以避免内存泄漏和提高内存利用率。
经典垃圾收集算法:标记清除算法产生大量内存碎片,复制算法浪费一半内存,标记整理算法效率较低但空间利用率高,现代垃圾收集器综合运用这些算法。
分代收集理论:根据对象存活周期的不同将内存划分为几块,新生代采用复制算法,老年代采用标记整理或标记清除算法,这是当前JVM垃圾收集的主流思路。
安全点与安全区域:用户线程执行到安全点时才能暂停下来进行垃圾收集,安全区域确保程序在不执行代码时也能进行垃圾收集。
类加载机制探秘
虚拟机把描述类的数据从Class文件加载到内存并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。
加载阶段:通过类的全限定名获取定义此类的二进制字节流,将字节流代表的静态存储结构转化为方法区的运行时数据结构,在内存中生成代表这个类的java.lang.Class对象。
验证阶段:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,包括文件格式验证、元数据验证、字节码验证和符号引用验证四个阶段。
准备阶段:为类变量分配内存并设置类变量初始值,这些变量所使用的内存都在方法区中进行分配,这里的初始值通常是指数据类型的零值。
解析阶段:将常量池内的符号引用替换为直接引用,符号引用是以一组符号来描述所引用的目标,直接引用是可以直接指向目标的指针或相对偏移量。
初始化阶段:真正开始执行类中定义的Java程序代码,根据程序员通过程序制定的主观计划去初始化类变量和其他资源,是执行类构造器clinit方法的过程。
性能优化实战指南
JVM性能调优是高级Java工程师的核心技能,合理的参数配置和监控可以显著提升应用性能。
G1收集器:面向服务端应用的垃圾收集器,将堆内存划分为多个大小相等的独立Region,可以预测GC停顿时间,适合大内存低延迟的应用场景。
ZGC收集器:Java 11引入的实验性收集器,基于染色指针和读屏障技术实现,在任何堆大小下停顿时间都不超过10毫秒,是未来JVM垃圾收集的重要方向。
JIT编译优化:即时编译器将字节码编译为本地机器码,包括方法内联、逃逸分析、锁消除等优化技术,显著提升热点代码的执行效率。
内存泄漏排查:使用MAT、VisualVM等工具分析堆转储快照,定位GC Roots到泄漏对象的引用链,找出导致对象无法被回收的根本原因。
监控指标体系:GC频率和停顿时间、堆内存使用率、类加载数量、线程状态等关键指标,通过JMX接口采集数据,建立完整的JVM监控体系。