📕我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)、《解密程序员的思维密码——沟通、演讲、思考的实践》作者、清华大学出版社签约作家、Java领域优质创作者、优快云博客专家、阿里云专家博主、51CTO专家博主、产品软文专业写手、技术文章评审老师、技术类问卷调查设计师、幕后大佬社区创始人、开源项目贡献者。
📘拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、SpringMVC、SpringCloud、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RocketMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。
📙不定期分享高并发、高可用、高性能、微服务、分布式、海量数据、性能调优、云原生、项目管理、产品思维、技术选型、架构设计、求职面试、副业思维、个人成长等内容。

💡在这个美好的时刻,笔者不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。

JVM知识体系概述
Java虚拟机(JVM)是Java语言的运行环境,它负责将Java字节码转换为机器码执行。JVM的设计考虑了内存管理、垃圾回收、多线程并发等多个复杂问题,以下是对JVM知识体系的详细解析。
类加载机制
类加载机制是JVM的核心功能之一,负责从文件系统或网络中加载Class文件,并将其转换成JVM能够使用的Java类型。类加载过程主要分为三个阶段:加载、连接和初始化。
-
加载:加载Class文件到JVM中,包括类的定义信息、静态字段、方法信息等。在这个过程中,JVM会检查类的名称是否合法,以及是否与已加载的类冲突。
-
连接:连接阶段包括验证、准备和解析三个子阶段。
- 验证:确保Class文件的字节码符合JVM规范,包括类文件格式、字节码结构、访问权限等。验证过程涉及对字节码的语法、语义和运行时行为的检查。
- 准备:为类变量分配内存,并设置默认初始值。对于基本数据类型,初始值为0;对于引用数据类型,初始值为null。
- 解析:将符号引用转换为直接引用。符号引用是类、接口、字段和方法的名称和类型,而直接引用是直接指向对象的引用。
-
初始化:执行类构造器方法( ()),初始化类变量和静态变量。初始化过程包括初始化类变量、静态初始化块和父类构造器方法。
双亲委派模型
双亲委派模型是JVM中类加载器的一种工作模式,它要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。当一个类加载器请求加载某个类时,它首先委托给父类加载器进行加载,只有当父类加载器无法完成加载任务时,才自己去尝试加载。这种模式确保了类加载的一致性和隔离性。
自定义类加载器
自定义类加载器允许开发者实现自己的类加载逻辑,例如加载特定格式的文件、实现模块化系统等。自定义类加载器需要继承java.lang.ClassLoader类,并重写findClass方法。
模块化系统(JPMS)
Java Platform Module System(JPMS)是Java 9引入的模块化系统,它允许将Java应用程序分解为多个模块,以提供更好的隔离性和可维护性。模块化系统通过模块描述文件(module-info.java)定义模块的依赖关系,并使用模块路径(module-path)指定模块的查找位置。
内存模型
JVM的内存模型包括运行时数据区和PC寄存器。
-
堆:所有线程共享的内存区域,用于存放几乎所有的对象实例和数组。堆内存是动态分配的,其大小可以通过JVM参数进行调整。
-
栈:每个线程拥有的独立内存空间,用于存放线程的局部变量和方法调用栈。栈内存的大小是固定的,通常在创建线程时指定。
-
方法区:用于存放已被虚拟机加载的类信息、常量、静态变量等数据。方法区的大小也是固定的,通常在JVM启动时指定。
-
PC寄存器:用于存储当前线程所执行的指令的地址。PC寄存器的大小与处理器架构有关。
内存溢出场景分析
内存溢出是指JVM内存不足,无法分配新的内存给对象或数组时发生的情况。常见的内存溢出场景包括:
- 创建对象过多:在短时间内创建大量对象,导致内存占用急剧增加。
- 大型数组创建:创建大型数组,如
int[] arr = new int[1000000000];,可能导致内存不足。 - 循环引用:循环引用会导致对象无法被垃圾回收,从而占用内存。
垃圾回收
垃圾回收(GC)是JVM自动回收不再使用的对象所占用的内存空间的过程。垃圾回收的触发条件包括:
- 系统空闲时间达到设定阈值
- 老年代空间不足
- 新生代空间不足
垃圾回收算法主要包括标记-清除、复制和标记-整理算法。
- 标记-清除:先标记所有可达对象,然后清除未被标记的对象。这种算法容易产生内存碎片。
- 复制:将内存分为两个部分,每次只使用其中一部分,当这部分空间不足时,将存活对象复制到另一部分,并清空原空间。这种算法避免了内存碎片,但牺牲了内存利用率。
- 标记-整理:在标记-清除算法的基础上,对内存进行整理,避免内存碎片。
GC Roots可达性分析
GC Roots是垃圾回收算法中的一个重要概念,它指的是从GC Roots开始,能够通过引用关系访问到的对象。只有当对象无法通过GC Roots访问时,才被认为是垃圾对象。常见的GC Roots包括:
- 栈帧中的本地变量表
- 方法区中的静态变量
- 方法区中的常量池
- 虚引用、弱引用和软引用的对象
- 反射创建的对象
- JNI本地方法创建的对象
分代收集理论
分代收集理论将JVM内存分为新生代(Young)和老年代(Old),分别采用不同的垃圾回收策略。
- 新生代:用于存放新创建的对象,采用复制算法或标记-清除算法。新生代空间较小,回收频率较高。
- 老年代:用于存放生命周期较长的对象,采用标记-清除、标记-整理或并发收集算法。老年代空间较大,回收频率较低。
引用类型
引用类型包括强引用、软引用、弱引用和虚引用。
- 强引用:最普通的引用类型,垃圾回收器不会回收强引用的对象。例如,
Object obj = new Object();就是一个强引用。 - 软引用:用于缓存,当内存不足时,垃圾回收器会回收软引用的对象。例如,
SoftReference<Object> softRef = new SoftReference<>(obj);就是一个软引用。 - 弱引用:与软引用类似,但垃圾回收器会立即回收弱引用的对象。例如,
WeakReference<Object> weakRef = new WeakReference<>(obj);就是一个弱引用。 - 虚引用:没有任何实际意义,用于跟踪对象被回收的情况。例如,
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, null);就是一个虚引用。
垃圾回收算法
垃圾回收算法主要包括标记-清除、复制和标记-整理算法。
- 标记-清除:先标记所有可达对象,然后清除未被标记的对象。这种算法容易产生内存碎片。
- 复制:将内存分为两个部分,每次只使用其中一部分,当这部分空间不足时,将存活对象复制到另一部分,并清空原空间。这种算法避免了内存碎片,但牺牲了内存利用率。
- 标记-整理:在标记-清除算法的基础上,对内存进行整理,避免内存碎片。
并发收集器
并发收集器允许垃圾回收与应用程序的运行同时进行,减少应用程序的停顿时间。
- CMS(Concurrent Mark Sweep):以最短停顿时间为目标,适用于对停顿时间要求较高的场景。CMS算法分为四个阶段:初始标记、并发标记、重新标记和并发清除。
- G1(Garbage-First):将堆内存划分为多个区域,优先回收垃圾回收价值最高的区域。G1算法分为多个阶段:初始标记、根区域扫描、并发标记、重新标记、混合收集和并发清理。
- ZGC(Z Garbage Collector):适用于多核处理器,以低延迟为目标。ZGC算法分为多个阶段:并发标记、并发垃圾回收和并发重置。
停顿时间控制策略
停顿时间控制策略包括:
- 最大停顿时间目标:设定一个最大停顿时间,垃圾回收器会尽量满足这个目标。
- 自适应停顿时间:根据应用程序的运行情况动态调整停顿时间。
性能调优
性能调优主要包括:
- JVM参数配置:通过调整JVM参数(如Xms、Xmx等)来优化性能。例如,可以设置堆内存大小、栈内存大小、垃圾回收策略等。
- 内存泄漏诊断:使用工具检测内存泄漏,并修复相关代码。常见的内存泄漏检测工具包括JProfiler、MAT等。
JIT编译优化
JIT编译器是JVM的一个重要组成部分,它负责将Java字节码编译成本地机器码,以提高程序执行效率。JIT编译器采用多种优化技术,例如:
- 常量折叠:将常量表达式在编译时进行计算,避免在运行时重复计算。
- 内联:将小的方法调用替换为方法体,减少方法调用的开销。
- 循环优化:优化循环结构,减少循环的开销。
- 分支预测:预测分支的执行方向,减少分支预测错误的开销。
Spring Boot知识体系概述
Spring Boot是一个开源的Java-based框架,用于简化Spring应用的初始搭建以及开发过程。以下是Spring Boot知识体系的详细解析。
自动配置
Spring Boot的自动配置功能可以根据类路径下添加的jar依赖自动配置Spring框架的相关功能。自动配置的实现依赖于条件化配置(@Conditional)和条件注解(@ConditionalOnClass、@ConditionalOnMissingBean等)。
@EnableAutoConfiguration原理
@EnableAutoConfiguration注解是Spring Boot自动配置的核心,它通过扫描类路径下的jar依赖,自动配置相应的Bean。SpringFactoriesLoader类负责加载类路径下META-INF/spring.factories文件中的自动配置类。
条件化配置(@Conditional)
条件化配置允许开发者根据特定的条件来决定是否应用某些配置。常见的条件注解包括:
- @ConditionalOnClass:当指定的类在类路径下存在时,应用配置。
- @ConditionalOnMissingBean:当指定的Bean不存在时,应用配置。
- @ConditionalOnProperty:当指定的属性值满足条件时,应用配置。
自定义Starter开发
自定义Starter允许开发者将特定的功能封装成jar包,方便其他开发者使用。自定义Starter需要创建一个Maven项目,并添加Spring Boot的依赖和自动配置类。
起步依赖、依赖管理机制
起步依赖是Spring Boot中用于简化依赖管理的概念,它将多个jar依赖打包成一个jar包。起步依赖通常以spring-boot-starter-开头,例如spring-boot-starter-web、spring-boot-starter-data-jpa等。
版本冲突解决
解决版本冲突的方法包括:
- 使用BOM文件(Bill of Materials)来管理依赖版本。BOM文件定义了所有依赖的版本信息,确保应用程序中使用的依赖版本一致。
- 使用依赖锁定策略。依赖锁定策略可以锁定特定版本的依赖,避免版本冲突。
第三方库集成模式
第三方库集成模式包括:
- 使用Spring Boot的自动配置功能。Spring Boot的自动配置功能可以自动配置第三方库,例如数据库连接池、缓存等。
- 手动配置Bean。通过配置Bean的方式集成第三方库,例如配置数据库连接池、缓存等。
Actuator、健康检查端点
Actuator是Spring Boot提供的一个端点,用于监控和管理应用程序。Actuator提供了多个端点,例如/health、/metrics、/info等。
度量指标收集
度量指标收集是指收集应用程序的性能数据,例如内存使用情况、线程数等。Spring Boot提供了Micrometer框架,用于收集和导出度量指标。
自定义Endpoint开发
自定义Endpoint允许开发者根据需求添加新的端点。自定义Endpoint需要继承org.springframework.boot.actuate.endpoint.Endpoint接口,并实现invoke方法。
配置文件管理
Spring Boot支持多种配置文件格式,例如application.yml和application.properties。配置文件可以定义应用程序的属性,例如数据库连接信息、缓存配置等。
多环境配置
多环境配置允许开发者为不同的环境(如开发、测试、生产)配置不同的配置文件。Spring Boot支持通过配置文件名区分不同环境的配置,例如application-dev.yml、application-test.yml、application-prod.yml。
配置加载优先级
配置加载优先级是指Spring Boot如何加载多个配置文件。Spring Boot会按照以下顺序加载配置文件:
- 根配置文件(例如:application.yml)
- 环境配置文件(例如:application-dev.yml)
- 指定配置文件(例如:application-dev.properties)
动态配置刷新
动态配置刷新允许开发者实时更新配置文件,而无需重启应用程序。Spring Boot支持通过Actuator端点实现动态配置刷新。
监控与日志
Spring Boot提供了一系列监控和日志功能,例如Actuator和Logback。Actuator可以监控应用程序的性能数据,而Logback可以配置日志级别和输出格式。
Micrometer集成
Micrometer是一个度量指标收集框架,可以与多种监控系统集成。Micrometer支持多种监控服务,例如Prometheus、Grafana等。
Logback/SLF4J配置
Logback和SLF4J是Java日志框架,Spring Boot支持它们的集成。Logback提供了丰富的日志级别和输出格式,而SLF4J提供了统一的日志接口。
分布式链路追踪
分布式链路追踪是指追踪分布式系统中各个组件之间的调用关系。Spring Boot支持使用Zipkin、Jaeger等分布式链路追踪工具。
扩展机制
Spring Boot提供了一系列扩展机制,例如自定义AutoConfigurationBean和生命周期扩展点。
响应式编程支持
Spring Boot支持响应式编程,例如使用Spring WebFlux框架。响应式编程可以提供更好的并发性能和可扩展性。
通过以上对JVM和Spring Boot知识体系的详细解析,我们可以看到这两个技术是如何相互关联和相互影响的。JVM作为Java语言的运行环境,为Spring Boot提供了基础,而Spring Boot则构建在JVM之上,提供了丰富的功能来简化Java应用的开发。在实际开发过程中,了解这两个技术的内在联系,将有助于我们更好地构建高性能、可维护的Java应用。

博主分享
📥博主的人生感悟和目标

📙经过多年在优快云创作上千篇文章的经验积累,我已经拥有了不错的写作技巧。同时,我还与清华大学出版社签下了四本书籍的合约,并将陆续出版。
- 《Java项目实战—深入理解大型互联网企业通用技术》基础篇的购书链接:https://item.jd.com/14152451.html
- 《Java项目实战—深入理解大型互联网企业通用技术》基础篇繁体字的购书链接:http://product.dangdang.com/11821397208.html
- 《Java项目实战—深入理解大型互联网企业通用技术》进阶篇的购书链接:https://item.jd.com/14616418.html
- 《Java项目实战—深入理解大型互联网企业通用技术》架构篇待上架
- 《解密程序员的思维密码--沟通、演讲、思考的实践》购书链接:https://item.jd.com/15096040.html
面试备战资料
八股文备战
| 场景 | 描述 | 链接 |
|---|---|---|
| 时间充裕(25万字) | Java知识点大全(高频面试题) | Java知识点大全 |
| 时间紧急(15万字) | Java高级开发高频面试题 | Java高级开发高频面试题 |
理论知识专题(图文并茂,字数过万)
| 技术栈 | 链接 |
|---|---|
| RocketMQ | RocketMQ详解 |
| Kafka | Kafka详解 |
| RabbitMQ | RabbitMQ详解 |
| MongoDB | MongoDB详解 |
| ElasticSearch | ElasticSearch详解 |
| Zookeeper | Zookeeper详解 |
| Redis | Redis详解 |
| MySQL | MySQL详解 |
| JVM | JVM详解 |
集群部署(图文并茂,字数过万)
| 技术栈 | 部署架构 | 链接 |
|---|---|---|
| MySQL | 使用Docker-Compose部署MySQL一主二从半同步复制高可用MHA集群 | Docker-Compose部署教程 |
| Redis | 三主三从集群(三种方式部署/18个节点的Redis Cluster模式) | 三种部署方式教程 |
| RocketMQ | DLedger高可用集群(9节点) | 部署指南 |
| Nacos+Nginx | 集群+负载均衡(9节点) | Docker部署方案 |
| Kubernetes | 容器编排安装 | 最全安装教程 |
开源项目分享
| 项目名称 | 链接地址 |
|---|---|
| 高并发红包雨项目 | https://gitee.com/java_wxid/red-packet-rain |
| 微服务技术集成demo项目 | https://gitee.com/java_wxid/java_wxid |
管理经验
【公司管理与研发流程优化】针对研发流程、需求管理、沟通协作、文档建设、绩效考核等问题的综合解决方案:https://download.youkuaiyun.com/download/java_wxid/91148718
希望各位读者朋友能够多多支持!
现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 💂 博客主页: Java程序员廖志伟
- 👉 开源项目:Java程序员廖志伟
- 🌥 哔哩哔哩:Java程序员廖志伟
- 🎏 个人社区:Java程序员廖志伟
- 🔖 个人微信号:
SeniorRD
🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~
470

被折叠的 条评论
为什么被折叠?



