类的加载机制
-
类加载的概念
- 类加载是 Java 虚拟机(JVM)把字节码文件(.class 文件)转变为 Java 类型的复杂且关键的过程。这就如同把一份详细的设计图纸(字节码文件)加工成一个可以实际运行和使用的软件模块(Java 类型)。字节码文件包含了类的完整定义,包括类的结构、成员变量、方法、构造函数等信息,类加载机制就是要把这些信息合理地加载到内存中,使得程序能够有效地利用这些类来执行各种操作。
-
类加载的时机
- 主动引用(一定会触发类加载)
- 创建类的实例:
- 当使用
new关键字创建对象时,JVM 会检查这个类是否已经加载。如果没有加载,就会触发类加载过程。这是因为在创建对象之前,JVM 需要知道这个类的结构信息,比如对象的大小、成员变量的布局等,这些信息都存储在类的字节码文件中,只有通过类加载才能获取。例如,对于一个自定义的Person类,当执行Person p = new Person();时,JVM 会首先加载Person类。
- 当使用
- 访问类的静态变量(除了被
final修饰的常量且在编译期就能确定值的情况):- 静态变量属于类本身,当访问一个类的静态变量时,JVM 需要确保这个类已经加载到内存中。对于非编译期确定值的
final静态变量,其初始化可能涉及到复杂的代码逻辑,所以访问这类变量会触发类加载。例如,有一个类Counter,其中有一个静态变量static int count;,当执行Counter.count时,就会触发Counter类的加载。但如果是final static int MAX_COUNT = 100;这种在编译阶段就能确定值的常量,JVM 在编译时就已经将其值放入常量池,访问它不会触发类加载,因为不需要再去加载类获取这个常量的值。
- 静态变量属于类本身,当访问一个类的静态变量时,JVM 需要确保这个类已经加载到内存中。对于非编译期确定值的
- 调用类的静态方法:
- 静态方法与类相关联,而不是与对象相关联。所以,当调用一个类的静态方法时,JVM 必须先加载这个类。例如,在一个
MathUtils类中有一个静态方法public static int add(int a, int b) { return a + b; },当执行MathUtils.add(1, 2);时,JVM 会加载MathUtils类,因为只有加载了这个类才能找到并执行add方法。
- 静态方法与类相关联,而不是与对象相关联。所以,当调用一个类的静态方法时,JVM 必须先加载这个类。例如,在一个
- 使用反射方式对类进行操作:
- 反射是 Java 中强大的机制,允许程序在运行时动态地获取类的信息并操作类。当使用
java.lang.reflect包中的方法,如Class.forName("com.example.MyClass")或者通过类的Class对象的newInstance()方法来创建类的实例时,会触发类加载。这是因为反射操作需要访问类的内部结构信息,而这些信息只有在类加载后才能获取。例如,在一个数据库连接框架中,通过Class.forName("com.mysql.jdbc.Driver")加载数据库驱动类,使得框架能够使用这个驱动类来建立数据库连接。
- 反射是 Java 中强大的机制,允许程序在运行时动态地获取类的信息并操作类。当使用
- 初始化一个类的子类:
- 当创建一个子类的对象时,JVM 会先检查父类是否已经加载。如果父类没有加载,就会先加载父类。这是因为子类继承了父类的成员变量和方法,子类的对象在内存中的布局和初始化过程依赖于父类的结构信息。例如,有一个父类
Animal和一个子类Dog,当执行Dog d = new Dog();时,JVM 会先加载Animal类,然后再加载Dog类。
- 当创建一个子类的对象时,JVM 会先检查父类是否已经加载。如果父类没有加载,就会先加载父类。这是因为子类继承了父类的成员变量和方法,子类的对象在内存中的布局和初始化过程依赖于父类的结构信息。例如,有一个父类
- 作为启动类(包含
main方法的类)被执行:- 包含
main方法的类是 Java 程序的入口点。当运行一个 Java 程序时,JVM 首先要加载这个启动类,因为main方法是程序执行的起点。例如,对于一个简单的HelloWorld程序,其包含main方法的HelloWorld类就是启动类,JVM 会先加载这个类,然后从main方法开始执行程序。
- 包含
- 创建类的实例:
- 被动引用(不会触发类加载)
- 通过子类引用父类的静态变量,不会导致子类的加载,只会加载父类:
- 当通过子类来访问父类的静态变量时,JVM 能够根据子类的信息找到父类的符号引用,并且只需要加载父类就可以获取这个静态变量的值。例如,父类
Parent有一个静态变量static int parentVar = 10;,子类Child,当执行System.out.println(Child.parentVar);时,只会加载Parent类,因为 JVM 可以通过Child类的继承关系找到Parent类中parentVar的定义,不需要加载Child类。
- 当通过子类来访问父类的静态变量时,JVM 能够根据子类的信息找到父类的符号引用,并且只需要加载父类就可以获取这个静态变量的值。例如,父类
- 定义类数组,不会触发类的加载:
- 定义一个类数组只是声明了一个可以存储该类对象的容器,并没有实际使用这个类的任何成员。例如,
A[] aArray = new A[10];只是在内存中分配了一个可以存储 10 个A类对象的空间,但没有创建A类的对象,也没有访问A类的静态成员,所以不会触发A类的加载。
- 定义一个类数组只是声明了一个可以存储该类对象的容器,并没有实际使用这个类的任何成员。例如,
- 通过子类引用父类的静态变量,不会导致子类的加载,只会加载父类:
- 主动引用(一定会触发类加载)
-
类加载的过程
- 加载(Loading)
- 字节码文件获取:
- 类加载器(ClassLoader)是类加载过程的核心角色。它负责根据类的全限定名(如
com.example.MyClass)来查找并获取类的字节码文件。字节码文件的来源多种多样。在最常见的本地文件系统场景下,类加载器会按照classpath环境变量指定的路径去查找.class 文件。例如,如果classpath包含了/project/src目录,当要加载com.example.MyClass类时,类加载器会在/project/src/com/example/MyClass.class路径下查找字节码文件。除了本地文件系统,字节码文件还可以来自网络,这在一些动态加载的应用场景中很有用,比如 Java Applet 或者一些基于网络的插件系统,类加载器可以通过网络协议(如 HTTP)从远程服务器下载字节码文件。另外,在一些特殊的应用场景下,字节码文件甚至可以从数据库或者其他自定义的存储介质中获取。
- 类加载器(ClassLoader)是类加载过程的核心角色。它负责根据类的全限定名(如
- 字节码文件转换为二进制流:
- 一旦找到字节码文件,类加载器会将其读取并转换为二进制字节流。这个过程类似于将文件从硬盘的存储格式转换为计算机能够处理的内存中的数据格式。对于本地文件系统中的.class 文件,类加载器会通过文件输入流(
FileInputStream)等机制读取文件内容,并将其转换为二进制字节流。这个字节流是后续操作的基础,它包含了类的所有信息,包括类的结构、方法代码、变量定义等。
- 一旦找到字节码文件,类加载器会将其读取并转换为二进制字节流。这个过程类似于将文件从硬盘的存储格式转换为计算机能够处理的内存中的数据格式。对于本地文件系统中的.class 文件,类加载器会通过文件输入流(
- 在内存中生成代表这个类的
java.lang.Class对象:- 在将字节码文件转换为二进制字节流之后,类加载器会在内存中创建一个
java.lang.Class对象来代表这个类。这个Class对象是 Java 反射机制的基石,它就像是类在内存中的一个 “代理” 或者 “身份证”。通过这个Class对象,可以访问和操作类的各种属性,如获取类的名称、访问类的方法、获取类的成员变量等。例如,可以通过Class对象的getName()方法获取类的名称,通过getMethods()方法获取类的所有方法信息。这个Class对象在内存中的存储位置和管理方式由 JVM 内部机制决定,它是类在内存中的一种抽象表示,使得 JVM 能够在运行时对类进行各种操作。
- 在将字节码文件转换为二进制字节流之后,类加载器会在内存中创建一个
- 字节码文件获取:
- 验证(Verification)
- 文件格式验证:
- 这是验证过程的第一步,主要检查字节码文件是否符合 Java 虚拟机规范的格式要求。字节码文件有一个特定的格式,开头部分是魔数(
CAFEBABE),这是一个用于标识字节码文件的特殊标记。验证过程会检查文件是否以正确的魔数开头,就像检查一个文件是否是合法的字节码文件的 “身份证” 一样。同时,还会检查文件的版本号是否在当前 JVM 支持的范围内。Java 字节码文件的版本号随着 Java 语言的发展而更新,JVM 只能处理与其兼容的版本号范围内的字节码文件。如果文件格式不符合要求,JVM 会抛出java.lang.VerifyError异常,拒绝加载这个类。
- 这是验证过程的第一步,主要检查字节码文件是否符合 Java 虚拟机规范的格式要求。字节码文件有一个特定的格式,开头部分是魔数(
- 元数据验证:
- 元数据验证主要关注类的元数据信息,即类的结构相关的信息。这包括检查类的父类是否正确,例如,一个类不能继承一个
final类,验证过程会检查这种非法的继承关系。同时,对于实现接口的类,会检查是否实现了接口中要求的所有方法。例如,如果一个类声称实现了java.util.List接口,那么就需要验证它是否实现了List接口中定义的所有方法,如add、remove、get等方法。此外,还会检查类的成员变量和方法的访问修饰符是否合法,例如,一个private方法不能在类外部被访问,验证过程会确保这种访问限制得到遵守。
- 元数据验证主要关注类的元数据信息,即类的结构相关的信息。这包括检查类的父类是否正确,例如,一个类不能继承一个
- 字节码验证:
- 字节码验证是对类的字节码指令进行详细检查,确保字节码流可以被虚拟机安全地执行。这是验证过程中最复杂的部分,因为它需要对字节码的逻辑和操作进行深入分析。例如,检查字节码是否存在非法的操作码,每个操作码在字节码文件中都有其特定的含义和规则,不合法的操作码可能会导致 JVM 执行错误的操作。同时,还会检查跳转指令是否指向合法的位置,字节码中的跳转指令用于实现循环、条件判断等逻辑结构,验证过程需要确保这些跳转指令不会导致程序执行到非法的内存区域或者跳过一些必要的初始化代码。如果字节码验证失败,JVM 会抛出
java.lang.VerifyError异常。
- 字节码验证是对类的字节码指令进行详细检查,确保字节码流可以被虚拟机安全地执行。这是验证过程中最复杂的部分,因为它需要对字节码的逻辑和操作进行深入分析。例如,检查字节码是否存在非法的操作码,每个操作码在字节码文件中都有其特定的含义和规则,不合法的操作码可能会导致 JVM 执行错误的操作。同时,还会检查跳转指令是否指向合法的位置,字节码中的跳转指令用于实现循环、条件判断等逻辑结构,验证过程需要确保这些跳转指令不会导致程序执行到非法的内存区域或者跳过一些必要的初始化代码。如果字节码验证失败,JVM 会抛出
- 符号引用验证:
- 在 Java 程序中,代码中的类、方法和变量等可能是通过符号引用来表示的。符号引用是一种在编译阶段使用的引用方式,它通过字符串来描述目标的名称和位置。在解析阶段,这些符号引用会被转换为直接引用,而在这之前需要进行符号引用验证。主要验证符号引用中通过字符串描述的全限定名是否能找到对应的类、字段和方法等。例如,当一个类
A引用了另一个类B时,在字节码文件中可能只是通过符号(如B的全限定名)来表示这个引用。符号引用验证会检查这个全限定名是否能够正确地定位到一个实际存在的B类。如果符号引用验证失败,JVM 会抛出java.lang.NoClassDefFoundError异常。
- 在 Java 程序中,代码中的类、方法和变量等可能是通过符号引用来表示的。符号引用是一种在编译阶段使用的引用方式,它通过字符串来描述目标的名称和位置。在解析阶段,这些符号引用会被转换为直接引用,而在这之前需要进行符号引用验证。主要验证符号引用中通过字符串描述的全限定名是否能找到对应的类、字段和方法等。例如,当一个类
- 文件格式验证:
- 准备(Preparation)
- 在准备阶段,JVM 会为类的静态变量分配内存空间,并设置默认初始值。这个过程是类加载过程中的一个重要环节,它主要是为后续的初始化阶段做准备。对于基本数据类型的静态变量,会根据其类型设置默认值。例如,对于
static int num;,JVM 会为num分配 4 个字节的内存空间(假设int类型占 4 个字节),并将其初始值设置为 0。对于static boolean flag;,会将其初始值设置为false。对于引用类型的静态变量,会将其初始值设置为null。需要注意的是,如果是static final常量,并且其值在编译期就能确定(如static final int CONST_NUM = 10;),那么在这个阶段会直接将其值设置为 10,而不是先设置为默认值再进行初始化。这是因为编译期确定值的常量在字节码文件中已经被当作一个常量值处理,不需要再经过初始化阶段。
- 在准备阶段,JVM 会为类的静态变量分配内存空间,并设置默认初始值。这个过程是类加载过程中的一个重要环节,它主要是为后续的初始化阶段做准备。对于基本数据类型的静态变量,会根据其类型设置默认值。例如,对于
- 解析(Resolution)
- 符号引用转换为直接引用:
- 在 Java 程序中,很多引用是通过符号引用来表示的。符号引用是一种在编译阶段使用的、比较抽象的引用方式,它通过字符串来描述目标的名称和位置。例如,当一个类
A引用了另一个类B时,在字节码文件中可能只是通过符号(如B的全限定名)来表示这个引用。解析阶段的一个重要任务就是将这些符号引用转换为直接引用。直接引用可以是指向目标的指针、相对偏移量或者能直接定位到目标的句柄。例如,将对类B的符号引用转换为指向B类在内存中Class对象的指针,这样在程序执行过程中,当需要访问B类时,就可以通过这个直接引用来快速定位到B类。
- 在 Java 程序中,很多引用是通过符号引用来表示的。符号引用是一种在编译阶段使用的、比较抽象的引用方式,它通过字符串来描述目标的名称和位置。例如,当一个类
- 解析类或接口、字段、方法的引用:
- 这包括对类和接口的加载和链接(如果还没有完成),以及对字段和方法的查找和绑定。例如,当一个类
A调用了另一个类B的方法method时,在解析阶段需要找到B类的method方法在内存中的位置,并建立起A类和B类method方法之间的调用关系。对于类和接口的解析,会检查引用的类或接口是否已经加载,如果没有加载,会触发加载过程。对于字段和方法的解析,会在类的字节码中查找对应的字段和方法的定义,并确定其在内存中的访问方式。这可能涉及到权限检查,例如,一个private方法只能在其所属的类内部被访问,如果在其他类中试图访问这个private方法,解析过程会检查这种访问是否合法。
- 这包括对类和接口的加载和链接(如果还没有完成),以及对字段和方法的查找和绑定。例如,当一个类
- 符号引用转换为直接引用:
- 初始化(Initialization)
- 执行类的初始化代码:
- 这是类加载过程的最后一步,会执行类的初始化代码。初始化代码包括静态变量的初始化语句和静态初始化块(
static {...})中的代码。这些代码会按照在类中出现的顺序依次执行。例如,对于一个类C,有static int num = 10;和static { System.out.println("Initializing C"); },在初始化阶段,会先将num的值初始化为 10,然后执行静态初始化块中的打印语句。初始化代码是类在加载后第一次被使用时执行的代码,它用于初始化类的静态资源,例如,初始化一个静态的数据库连接池、加载配置文件等操作。
- 这是类加载过程的最后一步,会执行类的初始化代码。初始化代码包括静态变量的初始化语句和静态初始化块(
- 初始化顺序:
- 如果一个类有父类,那么先初始化父类,再初始化子类。这是因为子类可能会继承父类的静态变量和静态方法,需要先确保父类的初始化完成,才能正确地初始化子类。而且,在初始化过程中,同一个类只会被初始化一次,这是通过一个标记位来控制的。当一个类开始初始化时,JVM 会设置一个标记,表示这个类正在初始化。如果在初始化过程中遇到对同一个类的再次初始化请求,JVM 会忽略这个请求,避免重复初始化导致的错误。
- 执行类的初始化代码:
- 加载(Loading)
-
类加载器(ClassLoader)
- 启动类加载器(Bootstrap ClassLoader)
- 它是 Java 虚拟机内置的类加载器,处于类加载器层次结构的最顶层。启动类加载器负责加载 Java 核心类库,这些核心类库对于 Java 程序的运行是至关重要的,如
java.lang.Object、java.util.ArrayList等。它使用原生代码(C/C++)来实现,这使得它能够高效地加载最基础的类库。由于其特殊的实现方式,启动类加载器没有对应的java.lang.ClassLoader对象,所以在 Java 代码中无法直接引用它。启动类加载器的加载路径是固定的,通常是<JAVA_HOME>/jre/lib目录下的核心类库,这些类库是经过严格测试和优化的,构成了 Java 运行环境的基础。
- 它是 Java 虚拟机内置的类加载器,处于类加载器层次结构的最顶层。启动类加载器负责加载 Java 核心类库,这些核心类库对于 Java 程序的运行是至关重要的,如
- 扩展类加载器(Extension ClassLoader)
- 扩展类加载器位于类加载器层次结构的第二层,它负责加载 Java 的扩展类库,即
<JAVA_HOME>/jre/lib/ext目录下的类库。扩展类加载器是由sun.misc.Launcher$ExtClassLoader实现的,它是java.lang.ClassLoader的子类。它可以加载一些第三方的扩展库,这些库提供了一些额外的功能,比如加密算法库、XML 解析库等。扩展类加载器的存在使得 Java 程序可以方便地扩展其功能,而不需要将所有的功能都集成在核心类库中。它的加载路径除了<JAVA_HOME>/jre/lib/ext目录外,还可以通过系统属性java.ext.dirs来指定其他扩展目录。
- 扩展类加载器位于类加载器层次结构的第二层,它负责加载 Java 的扩展类库,即
- 应用程序类加载器(Application ClassLoader)
- 也称为系统类加载器,它是类加载器层次结构中的第三层,负责加载用户类路径(
classpath)上的类库。它是sun.misc.Launcher$AppClassLoader实现的,也是java.lang.ClassLoader的子类。在大多数情况下,我们编写的 Java 程序中的类都是由应用程序类加载器加载的。它可以加载我们自己编写的类、第三方的库(如果这些库在classpath中)等。应用程序类加载器的加载路径可以通过系统属性classpath来指定,它会按照classpath中指定的目录和文件来查找和加载类。同时,它还会委托给其父类加载器(扩展类加载器和启动类加载器)来加载类,这是类加载器的委托机制的一部分。
- 也称为系统类加载器,它是类加载器层次结构中的第三层,负责加载用户类路径(
- 自定义类加载器(Custom ClassLoader)
- 除了上述三种标准的类加载器外,我们还可以根据自己的需求创建自定义类
- 启动类加载器(Bootstrap ClassLoader)
相关文章:
类的加载机制
类加载的概念 类加载是 Java 虚拟机(JVM)把字节码文件(.class 文件)转变为 Java 类型的复杂且关键的过程。这就如同把一份详细的设计图纸(字节码文件)加工成一个可以实际运行和使用的软件模块(J…...
基于vite创建的react18项目的单元测试
题外话 最近一个小伙伴进了字节外包,第一个活就是让他写一个单元测试。 嗯,说实话,在今天之前我只知道一些理论,但是并没有实操过,于是我就试验了一下。 通过查询资料,大拿们基本都说基于vite的项目&…...
fiddler抓包工具与requests库构建自动化报告
一. Fiddler 抓包工具 1.1 Fiddler 工具介绍和安装 Fiddler 是一款功能强大的 HTTP 调试代理工具,能够全面记录并深入检查您的计算机与互联网之间的 HTTP 和 HTTPS 通信数据。其主界面布局清晰,主要包含菜单栏、工具栏、树形标签栏和内容栏。 1.2 Fid…...
Docker login 报证书存储错误的解决办法
文章目录 docker login 出现错误,提示:Error saving credentials: error storing credentials - err: exit status 1, out: Cannot autolaunch D-Bus without X11 $DISPLAY 环境 使用的是 Mint Linux ,容器为 docker-ce 最新版 1 2 3 4 $…...
【自动化Selenium】Python 网页自动化测试脚本(上)
目录 1、Selenium介绍 2、Selenium环境安装 3、创建浏览器、设置、打开 4、打开网页、关闭网页、浏览器 5、浏览器最大化、最小化 6、浏览器的打开位置、尺寸 7、浏览器截图、网页刷新 8、元素定位 9、元素交互操作 10、元素定位 (1)ID定位 &…...
什么是MyBatis?
MyBatis简介 MyBatis是一款优秀的持久层框架,用于简化Java应用程序对数据库的操作。它曾是Apache的一个开源项目,名为iBatis,2010年迁移到Google Code并改名为MyBatis,2013年11月又迁移到了GitHub。 一、MyBatis的作用 在JavaE…...
TortoiseGit 将本地已有仓库推送到远程
TortoiseGit 将本地已有仓库推送到远程 一、创建线上仓库二、创建本地仓库三、提交内容到本地仓库四、添加远程仓库地址补充 一、创建线上仓库 在gitlab管理面页面按这前讲过的步骤创建一个空仓库。(通常我们把服务器上这个仓库叫远程仓库,把我们自己电…...
腾讯云OCR车牌识别实践:从图片上传到车牌识别
在当今智能化和自动化的浪潮中,车牌识别(LPR)技术已经广泛应用于交通管理、智能停车、自动收费等多个场景。腾讯云OCR车牌识别服务凭借其高效、精准的识别能力,为开发者提供了强大的技术支持。本文将介绍如何利用腾讯云OCR车牌识别…...
TailwindCss 总结
目录 一、简介 二、盒子模型相关 三、将样式类写到一个类里面apply 四、一款TailWind CSS的UI库 一、简介 官方文档:Width - TailwindCSS中文文档 | TailwindCSS中文网 Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类…...
Java与C#
Java和C#(C Sharp)是两种流行的面向对象编程语言,它们在很多方面非常相似,因为它们都受到了类似的编程范式和语言设计理念的影响。然而,它们之间也存在一些重要的区别。 平台依赖性: Java:Java是…...
leetcode:222完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最…...
[STM32]从零开始的STM32 FreeRTOS移植教程
一、前言 如果能看到这个教程的话,说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗?是的,我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS,再到最…...
java——Tomcat连接池配置NIO、BIO、APR
Tomcat连接池的配置涉及不同的IO模型,包括NIO(Non-blocking IO,非阻塞IO)、APR(Apache Portable Runtime,Apache可移植运行库)和BIO(Blocking IO,阻塞IO)。以…...
跨域相关的一些问题 ✅
当网页从一个源(https://baidu.com)请求另一个源(如 https://taobao/api)的资源时,就发生了跨域。由于安全原因(防止恶意网站通过脚本访问用户在其他网站上的数据),浏览器对跨域请求…...
RPC学习
一、什么是 RPC RPC(Remote Procedure Call),即远程过程调用,是一种计算机通信协议,它允许运行在一台计算机上的程序调用另一台计算机上的子程序或函数,就好像调用本地程序中的函数一样,无需程序…...
coe文件转mif(c语言)
1 mif文件格式 DEPTH=1024; --The size of data in bits WIDTH=16; --The size of memory in words ADDRESS_RADIX = DEC; --The radix for address values DATA_RADIX = UNS...
【leetcode】动态规划
31. 873. 最长的斐波那契子序列的长度 题目: 如果序列 X_1, X_2, ..., X_n 满足下列条件,就说它是 斐波那契式 的: n > 3对于所有 i 2 < n,都有 X_i X_{i1} X_{i2} 给定一个严格递增的正整数数组形成序列 arr ࿰…...
介绍一下atoi(arr);(c基础)
hi , I am 36 适合对象c语言初学者 atoi(arr);是返回整数(int型),整数是arr数组中字符中数字 格式 #include<stdio.h> atoi(arr); 返回值arr数组中的数字 未改变arr数组 #include<stdlib.h>//atoi(arr); 返 <stdlib> int main(…...
docker入门学习笔记
docker的定义 docker是一个用于构建、运行、传送 应用程序的平台。 为什么要使用docker ? 在开发测试库环境中测试成功后,打包成集装箱,到生产环境也是能够成功的。而传统的安装方式不仅繁琐,并且在测试环境安装后,到…...
使用Python和Pybind11调用C++程序(CMake编译)
目录 一、前言二、安装 pybind11三、编写C示例代码四、结合Pybind11和CMake编译C工程五、Python调用动态库六、参考 一、前言 跨语言调用能对不同计算机语言进行互补,本博客主要介绍如何实现Python调用C语言编写的函数。 实验环境: Linux gnuPython3.10…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
