🚀JVM系列 之 深入探索Java 类加载器
Hey 大家好,我是 Shio👋。今天我们将深入探讨 Java 的类加载器,这是 Java 虚拟机(JVM)中一个重要的概念。在上一篇中,我们了解到 Java 类加载分为多个步骤,其中只有加载步骤中的读取二进制流与初始化部分是由上层开发者控制的, 剩下的步骤都由 JVM 掌控 。 这是为了符合面向对象中的开闭原则和封装思想。
📦 类加载器的分类
首先要声明的是,类加载器的分类属于 JVM 规范,是一种抽象的概念。各个 JVM 的实现方式可能不同。在JVM 规范中,类加载器分为启动类加载器和非启动类加载器。本节我们只讲最常见和主流 HotSpot:
启动类加载器
Bootstrap Class Loader:
采用 C 和 C++ 实现,嵌套在 JVM 内部,无法被程序引用。
主要加载 Java 的核心类库,如 JAVA_HOME /lib 路径下的包(rt.jar tool.jar等)或由启动参数指定的核心类库。(-Xbootclasspath/a: jar包目录/jar包名 的类也会被其加载)
只加载包名在白名 ...
🌱JVM系列 之 自底向上理解Java内存模型
Hey 大家好,我是 Shio👋。今天我们将深入探讨Java 内存模型
⚠️ 注意!!!
🚧🚧🚧 本文并不完整, 还未彻底 完成🚧🚧🚧
💾内存模型发展
🚀 单处理器时代的纵向优化
在单处理器计算机时代,程序员只需编写单线程程序,除了算法降低复杂度外, 只能依赖硬件和编译器进行纵向优化。
随着硬件发展速度趋于平缓,工程师们开始追求横向拓展,即在单台计算机中使用更多的处理器。
👾 缓存的引入与多处理器时代的问题
为弥补CPU处理速度与内存读写速度的差距,引入了缓存以提高效率。然而,在多处理器环境下,缓存带来了数据不一致的问题。
🚧 缓存一致性协议的设计
为此科学家们设计了缓存一致性协议,解决多个CPU缓存之间的同步问题这些协议, 保证了数据的一致性。
大致分为窥探型和基于目录型。
可想而知, 为了保证多个CPU缓存一致性和同步, 协议中一定涉及到等待和唤醒等同步步骤
对于CPU这种运算速率极快的组件来说, 任何等待都是对其性能极大的浪费 (CPU A 在读取 D时还需要等待 CPU B 将D写回到内存)
🛠 ...
🌟 JVM系列 之 深入理解类加载机制
👥 背景故事
在一次友人间的聚餐讨论中,我们提及了不同编程语言的优势与学习深度。对于一位以PHP为背景的朋友,有人建议其转向Java生态,因为Java具有成熟的生态系统和广泛的应用场景。朋友表示自己也会Java, 掌握Java的语法 …
💡 学习层次剖析
学习编程语言可分为三个递进层次:
📚 基础语法核心类库的熟悉使用
🌐 优势劣势分析与生态系统了解
🔧 底层运行机制探究与应用优化
💻 Java核心 -JVM
Java的核心魅力在于Java虚拟机(JVM),它是跨平台执行Java字节码的关键。诸如Kotlin, Groovy、Scala等其他基于JVM的语言,通过深入理解JVM可以更高效地掌握。
📖 类加载机制详解
编译与执行:Java源代码经过javap编译转换成.class字节码文件,由JVM加载并解析执行,同时即时编译器(JIT)会将热点代码转化为高效的二进制代码, 通过解释器和即时编译器想结合预热后的代码可以达到很快的执行效率
类加载流程
加载阶段:加载阶段的任务是读取字节码资源以静态结构的形式存储在方 ...
Spring
未读渐进式实现Spring日志
1 开始实现一个简单的Spring Bean容器
1.1 设计思路
使用Map数据结构来存储所有的Bean对象。
2. 基于模板模式实现对象定义、注册和获取
2.1 设计思路
使用模板模式,统一使用核心方法的调用逻辑和标准定义,进而可以很好地实现后续步骤而不用关心某一方法的调用逻辑。按照统一方式执行,类的继承者只需要关心具体方法如何实现即可。
基于模板方法模式实现对象定义, 注册, 获取
SingletonBeanRegistry- 获取单例的注入和获取能力DefaultSingletonBeanRegistry- 内部维护singletonObjectsMap, 提供单例对象的管理能力BeanFactory- 获取Bean的能力AbstractBeanFactory- 提供getBean的模板方法实现 - 获取单例, 获取成功直接返回(利用父类DefaultSingletonBeanRegistry) - 获取BeanDefinition 抽象方法交给子类实现 - 创建Bean实例 抽象方法交给子类实现 DefaultAutowireCapableB ...
【Java版本】常用代码模板
-------基础算法-------
排序
快速排序
代码模板
private void quickSort(int[] arr, int left, int right) { // 递归终止条件,如果左边界大于等于右边界则认为递归结束 if (left >= right) { return arr; } // 设定一个分界值,这里是(left + right)/ 2 int p = arr[left + right >> 1]; // 左右提前预留一个位置 int i = left - 1; int j = right + 1; while (i < j) { // 等效于do while // 当数值小于分界值时持续遍历,直到找到第一个大于等于分界值的索引 // 如果是逆序则调整两个while循环 while (arr[++i] < p) ...
设计模式之美----职责链模式
本文将对责任链模式(职责链模式)分为四个部分进行讲解
原理
实现
应用
练习
让大家系统全面的学会使用责任链模式, 并应用到开发中去
原理篇
大部分设计模式的核心是应对工程中的复杂性, 使得代码满足开闭原则, 提高代码扩展性
职责链的英文名为Chain Of Responsibility Design Pattern, 在GoF的设计模式中的定义如下
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
“将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。”
实际上就是将请 ...
2382bfe48e84f4ceee293ec9c487c2858b4a752663d25a909ab793385f4a18a442f7657e89e8da5dca6a4c6168efa9eb90ffbd7076fdde43939227b91260f4f603f1cc0ba1695bcd137dffa2723f907aec8a48cadfdfe34867d9f4aee7df6e123aa3868d7ec9aa9da330e63be491163db789d88fe5beb1a641f62cfede1ace3d5be01724b44fa5f0652f8e3813ff79b424b702a1ca38015049b54ce51b9e7a2e535c1922d18266c6f9fdfad4e491819e9515290d57c0efc1240fe8020ba265c30c95728c58997b8ef812610a4054c6ffa501284a2bacee606399169957331e7e3fc1782171928f99950dd4144aafe9fa4c313d3aff9825ec9 ...
Redis最佳实践
🎉 本文, 我们将深入探索 Redis,一个强大且实用的开源内存数据库 , 以键值对形式提供数据结构存储服务。
概述
💾始于缓存
在常见的 Web 应用架构中,静态内容(如 HTML、CSS、JS、图片等)可通过 CDN 或 nginx 缓存;而对于数据库中的动态数据,为减轻后端数据库的压力,可利用 Redis 来缓存那些不常变更的部分。
🔒 Redis 不止于缓存
除作为缓存工具外,Redis 还能充当分布式锁的角色,确保在高并发场景下的数据一致性。此外,它还提供了丰富的高效数据结构与算法供开发者使用
📚 Redis 数据结构一览
Redis 常用的数据结构包括但不限于:
String:基本的键值对存储。
List:双向链表,支持两端插入、弹出元素。
Set:无序集合,自动去重。
Sorted Set:有序集合,每个成员带有分数属性,按分数排序。
Hash:键值对集合,适用于存储对象型数据。
💡 学习策略
面对可能略显枯燥的 Redis 命令,我们的学习策略是结合实际应用场景逐一解析,让理论知识与实践操作紧密结合,便于理解与记忆。
📢 ...
前言
为什么需要 Aware?
Aware 能将业务代码和框架功能解耦,本质上就是自定义 Bean 后置处理器,在框架类代码中可以用来暴露自己的内部成员。类似这样的设计在很多框架中都有体现,用于给外部做扩展。
Spring 依赖注入的最大特点就是所有Bean 对象 对于 Spring 容器的存在是无感知的。但是在实际项目中,我们还是要用到 Spring 容器内部所提供的资源(通过 Bean 调用 Spring 容器组件资源)
举个实际案例,以下内容是我询问 chatgpt 所得到的回答。
Q:
请举一个使用 bean 需要知道 Spring 容器的案例,以证明 Aware 接口的必要性
A:
一个典型的案例是使用 ApplicationContextAware 接口,该接口使得我们能够在 Bean 中直接获取 Spring 容器,从而实现更高级别的操作。
举个例子,假设我们需要在一个自定义的 Bean 中使用 Spring 容器中的某些资源(如Bean、Properties文件等),如果不使用Aware接口,我们通常需要手动创建一个BeanFactory或者ApplicationCon ...
日志
前几节内容,我们初步实现了一个容器、定义 Bean、注册 Bean 、实例化,按照是否包含构造函数实现不同的实例化策略。
本章节有以下变动:
查询类中是否有属性,如果类中包含属性,在实例化时注入属性信息。对于属性的填充不只是 int、Long、String,还包括还没有实例化的对象属性,都需要在 Bean 创建时进行填充操作。不过这里我们暂时不会考虑 Bean 的循环依赖,否则会把整个功能实现撑大,这样新人学习时就把握不住了,待后续陆续先把核心功能实现后,再逐步完善
设计
架构图
鉴于属性填充是在 Bean 使用 newInstance 或者 Cglib 创建后,开始补全属性信息,那么就可以在类 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加补全属性方法。
属性填充要在类实例化创建之后,也就是需要在 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加 applyPropertyValues 操作。
由于我们需要在创建Bean时候填充属性操作,那么就需要在 b ...