JVM/Spring Boot知识体系

📕我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、阿里云专家博主、51CTO专家博主、产品软文专业写手、技术文章评审老师、技术类问卷调查设计师、幕后大佬社区创始人、开源项目贡献者。

📘拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、SpringMVC、SpringCloud、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RocketMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。不定期分享高并发、高可用、高性能、微服务、分布式、海量数据、性能调优、云原生、项目管理、产品思维、技术选型、架构设计、求职面试、副业思维、个人成长等内容。

Java程序员廖志伟

🌾阅读前,快速浏览目录和章节概览可帮助了解文章结构、内容和作者的重点。了解自己希望从中获得什么样的知识或经验是非常重要的。建议在阅读时做笔记、思考问题、自我提问,以加深理解和吸收知识。阅读结束后,反思和总结所学内容,并尝试应用到现实中,有助于深化理解和应用知识。与朋友或同事分享所读内容,讨论细节并获得反馈,也有助于加深对知识的理解和吸收。💡在这个美好的时刻,笔者不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。

CSDN

JVM知识体系详解

类加载机制

Java虚拟机(JVM)的类加载机制是Java运行时的核心之一,它确保了Java代码的安全性、稳定性和效率。在类加载过程中,JVM通过类加载器负责将.class文件从文件系统或网络加载到JVM中,并生成相应的java.lang.Class对象。类加载机制主要分为以下几个阶段:

  1. 加载:类加载器负责查找和加载指定的.class文件。这个过程涉及到类加载器的加载策略和搜索路径。在Java中,主要有四种类型的类加载器:Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader和用户自定义类加载器。Bootstrap ClassLoader负责加载核心库,如rt.jar;Extension ClassLoader负责加载扩展库;System ClassLoader负责加载应用程序类路径(classpath)中的类;用户自定义类加载器可以按需定义,实现特定的加载逻辑。

  2. 验证:验证阶段确保加载的类信息符合JVM规范,防止恶意代码对JVM造成破坏。验证过程包括:文件格式验证、元数据验证、字节码验证和符号引用验证。

  3. 准备:准备阶段为类变量分配内存并设置默认初始值。对于基本数据类型,如intfloat等,其初始值为0;对于引用类型,如Object,其初始值为null

  4. 解析:解析阶段将符号引用转换为直接引用。符号引用是指类、接口、字段和方法的符号名称和字面量,而直接引用是指直接指向对象的指针、偏移量或方法句柄。

  5. 初始化:初始化阶段是类加载过程的最后一个阶段,它执行类定义中指定的构造器方法(<clinit>()),给类变量赋予正确的初始值。初始化过程包括:执行静态代码块、执行静态初始化器方法、设置类变量的初始值。

双亲委派模型

双亲委派模型是Java类加载机制的核心设计之一,它要求除了顶层的启动类加载器(Bootstrap ClassLoader)外,其余的类加载器都应当有自己的父类加载器。在加载类时,类加载器首先委托父类加载器进行加载,只有当父类加载器无法完成加载任务时,才自己尝试加载。这种设计可以避免类的重复加载,保证类型的全局唯一性,同时简化类加载过程。

自定义类加载器

自定义类加载器可以让我们控制类的加载过程,实现特定的功能,如模块化系统。自定义类加载器需要继承java.lang.ClassLoader类,并重写findClass()方法,实现类的查找和加载逻辑。在自定义类加载器中,我们可以根据需要修改类加载过程,例如:实现热部署、实现代码混淆、实现代码加密等。

模块化系统(JPMS)

Java Platform Module System(JPMS)是Java 9引入的一种模块化系统,旨在解决之前版本中JVM的依赖性和性能问题。它通过将代码划分为独立的模块来提高系统性能和安全性。JPMS的核心特性包括:

  1. 模块定义:模块定义文件(module-info.java)用于声明模块的依赖关系、模块的公开API和模块的私有API。

  2. 模块版本:模块版本采用语义版本控制,包括主版本号、次版本号和修订号。

  3. 模块依赖:模块之间的依赖关系通过模块定义文件中的requiresusesprovidesexports关键字进行声明。

  4. 模块解析:模块解析器根据模块依赖关系,确定模块的加载顺序和依赖关系。

  5. 模块加载:模块加载器根据模块定义文件和模块依赖关系,将模块加载到JVM中。

内存模型

JVM的内存模型由多个运行时数据区组成,这些数据区分别负责存储不同的数据类型和对象。

  1. :堆是JVM中最大的内存区域,用于存储几乎所有的Java对象实例和数组。堆被所有线程共享,垃圾回收器主要在堆上工作。

  2. :每个线程有一个栈,用于存储局部变量和方法调用等。栈是线程私有的,栈空间相对较小,但访问速度较快。

  3. 方法区:方法区存储已经被虚拟机加载的类信息、常量、静态变量等。方法区被所有线程共享,其空间相对较小。

  4. PC寄存器:每条线程有一个PC寄存器,指向当前执行的方法指令。PC寄存器是线程私有的,用于控制线程的执行流程。

内存溢出场景分析

内存溢出通常发生在堆空间不足时,常见场景包括:

  • 创建大量对象:例如,创建大量小对象或大对象,导致堆空间耗尽。

  • 长期存在内存泄漏:例如,对象生命周期过长,导致无法被垃圾回收器回收。

  • 方法区或栈溢出:例如,加载大量类信息或方法信息,导致方法区空间不足;或递归调用深度过大,导致栈空间不足。

垃圾回收

垃圾回收(GC)是JVM自动内存管理的关键,它通过标记-清除、复制、整理等算法回收不再使用的对象占用的内存。垃圾回收的主要目标是减少内存占用,提高系统性能。

  1. 标记-清除:标记-清除算法首先标记所有可达对象,然后清除未被标记的对象。这种算法的缺点是会产生内存碎片。

  2. 复制:复制算法将对象在堆中分成两半,每次只使用一半,当这一半快满时,将存活的对象复制到另一半,然后清空原一半。这种算法的缺点是空间利用率较低。

  3. 整理:整理算法类似于复制算法,但在移动对象时会整理内存,减少内存碎片。

GC Roots可达性分析

GC Roots是一组特殊的对象,用于标记那些可达的对象。垃圾回收器通过遍历这些对象来确定哪些对象是不可达的。常见的GC Roots包括:

  • 栈中的引用变量
  • 方法区中的静态变量
  • 方法区中的常量池
  • 本地方法栈中的JNI引用
分代收集理论

分代收集理论将对象分为几代,通常是新生代(Young)和老年代(Old)。新生代对象存活时间短,回收频率高;老年代对象存活时间长,回收频率低。分代收集的主要目的是提高垃圾回收效率。

  1. 新生代:新生代主要存放新创建的对象,其回收频率较高。新生代采用复制算法进行垃圾回收,分为Eden区和两个Survivor区。

  2. 老年代:老年代存放存活时间较长的对象,其回收频率较低。老年代采用标记-清除或标记-整理算法进行垃圾回收。

引用类型

引用类型包括强(Strong)、软(Soft)、弱(Weak)和虚(Phantom)引用。不同类型的引用对垃圾回收的影响不同。

  1. 强引用:强引用是默认的引用类型,只要存在强引用,对象就不会被垃圾回收器回收。

  2. 软引用:软引用用于缓存,当内存不足时,垃圾回收器会回收软引用指向的对象。

  3. 弱引用:弱引用用于实现缓存淘汰策略,当内存不足时,垃圾回收器会回收弱引用指向的对象。

  4. 虚引用:虚引用是弱引用的加强版,它没有任何实际意义,只能通过引用队列来获取。

垃圾回收算法
  1. 标记-清除:标记-清除算法首先标记所有可达对象,然后清除未被标记的对象。这种算法的缺点是会产生内存碎片。

  2. 复制:复制算法将对象在堆中分成两半,每次只使用一半,当这一半快满时,将存活的对象复制到另一半,然后清空原一半。这种算法的缺点是空间利用率较低。

  3. 整理:整理算法类似于复制算法,但在移动对象时会整理内存,减少内存碎片。

并发收集器

并发收集器允许垃圾回收与应用程序线程并发执行,常见的有CMS(Concurrent Mark Sweep)和G1(Garbage-First)收集器。

  1. CMS(Concurrent Mark Sweep):CMS收集器是一种以降低停顿时间为目标的并发收集器,适用于对停顿时间要求较高的场景。

  2. G1(Garbage-First):G1收集器是一种面向服务端应用的垃圾回收器,适用于多核处理器和大型堆的场景。

停顿时间控制策略

JVM提供了多种策略来控制垃圾回收时的停顿时间,如G1的Garbage-First和CMS的并发标记和清除。

  1. Garbage-First(G1):G1收集器通过将堆内存划分为多个区域,优先回收垃圾回收价值最高的区域,从而降低停顿时间。

  2. 并发标记和清除(CMS):CMS收集器通过并发标记和清除来降低停顿时间,但可能会产生内存碎片。

性能调优

性能调优涉及JVM参数配置(如Xms、Xmx等)、内存泄漏诊断和JIT编译优化。

  1. JVM参数配置:通过调整JVM参数,如堆大小、栈大小、垃圾回收策略等,来优化JVM性能。

  2. 内存泄漏诊断:通过内存分析工具,如MAT(Memory Analyzer Tool)和VisualVM,来诊断和修复内存泄漏问题。

  3. JIT编译优化:JIT编译器可以将Java字节码编译成机器码,从而提高程序执行效率。通过调整JIT编译器参数,可以优化JIT编译过程。

Spring Boot知识体系详解

自动配置

Spring Boot的自动配置是基于条件化配置实现的。当Spring Boot启动时,它会自动配置应用所需的所有Bean。自动配置的核心是@EnableAutoConfiguration注解。

  1. @EnableAutoConfiguration原理@EnableAutoConfiguration通过扫描类路径下的jar包,找到所有配置类,并利用条件化配置来选择合适的配置。条件化配置主要基于以下条件:

    • 条件注解:例如@SpringBootApplication@ConditionalOnClass@ConditionalOnMissingBean等。
    • 条件属性:例如spring.datasource.urlspring.datasource.username等。
  2. 条件化配置(@Conditional:条件化配置允许我们根据特定条件选择性地启用或禁用某些配置。例如,当存在某个类时,才启用相应的配置。

自定义Starter开发

自定义Starter可以帮助我们快速集成第三方库到Spring Boot应用中。自定义Starter需要创建一个Maven或Gradle项目,并添加相应的依赖和配置。

  1. 创建自定义Starter:创建一个Maven或Gradle项目,并添加Spring Boot依赖和自定义配置。

  2. 添加依赖:将第三方库添加到自定义Starter的依赖中。

  3. 配置文件:在自定义Starter中添加配置文件,例如application.propertiesapplication.yml

  4. 自动配置:在自定义Starter中添加自动配置类,实现自动配置逻辑。

起步依赖

起步依赖(Starter Dependencies)是Spring Boot项目的一部分,它们包含了创建独立运行项目所需的全部依赖。起步依赖简化了项目依赖管理,提高了开发效率。

  1. 起步依赖的组成:起步依赖通常包含以下组件:

    • 核心依赖:例如Spring Boot核心库、Spring Web等。
    • 依赖关系:例如数据库连接池、ORM框架等。
    • 依赖版本:起步依赖中包含了所有依赖的版本信息。
  2. 依赖管理机制:Maven或Gradle等构建工具使用BOM(Bill of Materials)文件来管理项目依赖的版本。BOM文件定义了所有依赖的版本信息,确保项目中的依赖版本一致。

版本冲突解决

版本冲突通常发生在多个依赖项引入了同一库的不同版本时。Spring Boot通过选择合适的版本号来解决这个问题。

  1. 依赖树分析:分析项目依赖树,找出版本冲突的依赖项。

  2. 选择合适的版本号:根据依赖关系和版本兼容性,选择合适的版本号。

  3. 依赖排除:使用<exclusions>标签排除冲突的依赖项。

第三方库集成模式

Spring Boot提供了多种集成第三方库的模式,包括自动化配置、依赖注入和事件驱动等。

  1. 自动化配置:通过添加相应的起步依赖和自动配置类,实现第三方库的自动化配置。

  2. 依赖注入:使用Spring框架的依赖注入功能,将第三方库的实例注入到Spring容器中。

  3. 事件驱动:使用Spring框架的事件驱动机制,实现第三方库的事件监听和响应。

Actuator

Spring Boot Actuator是一个提供生产级应用监控和管理功能的模块。它允许我们通过HTTP端点获取应用的运行时信息。

  1. Actuator端点:Actuator提供了多种端点,例如:

    • /health:获取应用的运行状态。
    • /metrics:获取应用的性能指标。
    • /info:获取应用的元数据信息。
    • /logs:获取应用的日志信息。
  2. 自定义Endpoint开发:我们可以自定义Endpoint来提供特定于应用的监控和管理功能。

配置文件管理

Spring Boot支持多环境配置,允许我们根据不同的环境加载不同的配置文件(如application-{profile}.yml)。

  1. 多环境配置:Spring Boot支持通过application-{profile}.yml文件实现多环境配置,例如:

    • application-dev.yml:开发环境配置。
    • application-test.yml:测试环境配置。
    • application-prod.yml:生产环境配置。
  2. 配置加载优先级:配置加载的优先级遵循“先配置,后覆盖”的原则。例如,如果同时存在application.ymlapplication-dev.yml,则application-dev.yml中的配置会覆盖application.yml中的配置。

动态配置刷新

Spring Boot允许我们动态刷新配置,以便在运行时修改配置而不需要重启应用。

  1. 配置刷新机制:Spring Boot使用@RefreshScope注解来实现配置刷新。当配置发生变化时,Spring容器会自动刷新具有@RefreshScope注解的Bean。

  2. 配置刷新方式:配置刷新可以通过以下方式实现:

    • HTTP请求:通过HTTP请求触发配置刷新。
    • 命令行:通过命令行参数触发配置刷新。
    • 消息队列:通过消息队列触发配置刷新。
监控与日志

Spring Boot与Micrometer集成,提供了多种监控工具。同时,它支持Logback/SLF4J等日志框架。

  1. 监控工具:Spring Boot支持的监控工具包括:

    • Micrometer:用于收集和导出应用性能指标。
    • Prometheus:用于监控和告警。
    • Grafana:用于可视化监控数据。
  2. 日志框架:Spring Boot支持的日志框架包括:

    • Logback:用于日志记录和日志管理。
    • SLF4J:用于日志门面。
分布式链路追踪扩展机制

Spring Boot支持分布式链路追踪,可以通过自定义配置来扩展链路追踪功能。

  1. 分布式链路追踪:分布式链路追踪是一种用于追踪分布式系统中请求路径的技术。Spring Boot支持以下分布式链路追踪框架:

    • Zipkin
    • Jaeger
  2. 自定义配置:通过自定义配置,我们可以选择合适的分布式链路追踪框架,并配置相关参数。

自定义AutoConfigurationBean生命周期扩展点

我们可以通过实现@Conditional注解来扩展AutoConfigurationBean的生命周期。

  1. AutoConfigurationBean生命周期:AutoConfigurationBean的生命周期包括:

    • 初始化:创建AutoConfigurationBean实例。
    • 销毁:销毁AutoConfigurationBean实例。
  2. 扩展生命周期:通过实现@Conditional注解,我们可以控制AutoConfigurationBean的生命周期,例如:

    • 在初始化阶段添加自定义逻辑。
    • 在销毁阶段添加自定义逻辑。
响应式编程支持

Spring Boot支持响应式编程,通过Reactor、Project Reactor等库实现。

  1. 响应式编程:响应式编程是一种异步编程范式,它允许程序以非阻塞的方式处理事件。

  2. 响应式编程库:Spring Boot支持的响应式编程库包括:

    • Reactor:用于构建响应式应用程序。
    • Project Reactor:用于构建响应式流应用程序。

通过以上对JVM和Spring Boot知识体系的详细解析,我们可以更深入地理解Java虚拟机的工作原理和Spring Boot框架的核心特性。这些知识对于Java开发者和架构师来说至关重要,有助于提高代码质量、优化系统性能和解决实际问题。

CSDN

📥博主的人生感悟和目标

Java程序员廖志伟

希望各位读者大大多多支持用心写文章的博主,现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!

- 💂 博客主页Java程序员廖志伟
- 👉 开源项目Java程序员廖志伟
- 🌥 哔哩哔哩Java程序员廖志伟
- 🎏 个人社区Java程序员廖志伟
- 🔖 个人微信号SeniorRD

Java程序员廖志伟

📙经过多年在CSDN创作上千篇文章的经验积累,我已经拥有了不错的写作技巧。同时,我还与清华大学出版社签下了四本书籍的合约,并将陆续出版。这些书籍包括了基础篇进阶篇、架构篇的📌《Java项目实战—深入理解大型互联网企业通用技术》📌,以及📚《解密程序员的思维密码--沟通、演讲、思考的实践》📚。具体出版计划会根据实际情况进行调整,希望各位读者朋友能够多多支持!

🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值