Java技术整理(1)—— JVM篇
1、什么是JVM?
JVM是一个可运行Java代码的虚拟计算机,包括一套字节码指令集,一组寄存器,一个栈,一个垃圾回收,堆和一个存储方式栈。JVM 是运行在操作系统之上,并不与操作系统直接交互。
2、运行过程:
我们都知道Java源文件,通过编译器,能够产生相应的.class文件,也就是字节码文件,而字节码文件又通过Java虚拟机中的解释器,编译成特定机器上的机器码。
如下:Java 源文件 —— 编译器 —— 字节码文件 —— JVM —— 机器码
每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这就是 Java 跨平台机制。
- 多个程序启动就会存在多个虚拟机实例,随程序的开始和完成而创建和消亡
- 多个虚拟机实例之间数据不能共享
2.1 线程
这里的线程指程序执行过程中的一个线程实体,在Hotspot JVM中的Java 线程与操作系统线程有直接的映射关系。
① 当线程本地存储、缓冲池分配、同步对象、栈、程序计数器等准备好以后,创建一个操作系统线程,随着Java线程的生命周期而变化,OS负责调度所有线程并分配CPU。
② OS线程完成初始化,调用Java线程的run()
方法
③ Java线程结束时,释放绑定OS线程和线程所有资源。
Hotspot JVM 后台运行的主要系统线程
- 虚拟机线程: 等待JVM到达安全点操作出现,这些操作必须在独立的线程中执行,因为当 堆 修改时需要JVM到达安全点。操作主要有 stop-the-world 垃圾回收、线程栈 dump、线程暂停、线程偏向锁解除。
- 周期任务线程: 负责定时器任务(即中断),用来调度周期性操作的执行。
- GC线程: 支持JVM的各种GC活动。
- 编译器线程: 支持在运行时将字节码动态编译成本地平台相关的机器码。
- 信号分发线程: 支持接收发送到JVM的信号并调用适当的JVM方法处理。
2.2 JMM 内存模型
- 私有型内存区域: 生命周期与线程相同,依赖用户线程的创建或结束(在Hotspot JVM中,每个线程都与OS线程直接映射)
- 程序计数器: 唯一不会发生OOM的区域
- 一块很小的内存空间,是当前线程所执行的字节码行号指示器,每一个线程都有一个独立的程序计数器。
- 若正在执行Java方法,计数器记录的是字节码指令的地址(当前指令的地址),若为本地方法(Native Method)则设为空。
- 虚拟机栈: 描述Java方法执行的内存模型。每一个方法执行时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,栈帧对应着方法的开始到结束的过程。
- 栈帧: 是一个存储数据和部分计算结果的数据结构,同时用来处理动态链接、方法返回值和异常分派等信息,无论如何完成方法(正常或异常)都会随着方法结束而销毁。
- 本地方法栈: 为Native方法服务的栈结构。
- 程序计数器: 唯一不会发生OOM的区域
- 共享型内存区域:
- 方法区(永久代): 存储加载的类信息、常量、静态变量、即时编译后的代码等数据。
- 运行时常量池: 方法区的一部分,主要用于存储在类加载后,编译期产生的字面量和符号引用。
- 类实例区(堆内存): 存储创建的对象和数组的内存区域,是GC最重要的内存区域。
- 方法区(永久代): 存储加载的类信息、常量、静态变量、即时编译后的代码等数据。
- 直接型内存区域: 不受JVM GC管理
2.3 JVM 运行时内存
JVM 堆从GC的角度可以细分为 新生代 和 老年代。
2.3.1 新生代
新生代 在JVM 堆内存中占有 1/3 的空间,老年代占有 2/3 的空间。
新生代区域 可分为三个部分:Eden区(8/10)、ServivorFrom区(1/10)、ServivorTo区(1/10)
- Eden区: Java新对象的存储区域(若新对象过大,则会直接放入老年代区),当该区域内存不足时,则会触发Minor GC 进行新生代区回收。
- ServivorFrom区: 存储上一次GC未回收的对象
- ServivorTo区: 保留一次Minor GC 未回收对象。
Minor GC(次要垃圾收集)
- 采用算法: 复制算法
- MinorGC的过程: 复制——清空——互换
新生代进行垃圾回收的过程:
- 1、eden、servivorFrom 复制到 servivorTo, 并且所有对象年龄+1
- 若对象年龄符合老年代标准,则复制到老年代
- 若ServivorTo区域内存不足,则直接复制到老年代
- 2、清空edon、servivorFrom区域
- 3、ServivorFrom与ServivorTo指针互换
- 在下一次GC时,现在的ServivorFrom就是需要扫描的ServivorTo
2.3.2 老年代
老年代主要是存放应用程序中生命周期长的内存对象,因为对象的稳定,所以不会频繁发生MajorGC。
- 当有新生代对象进入老年代时,先触发一次MajorGC,再触发MajorGC。
- 当无法找到足够的内存空间分配给新创建的较大对象时,也会触发MajorGC腾出空间。
- 当老年代内存不足时,抛出OOM异常。
Major GC(主要垃圾回收)
- 采用算法: 标记清除算法。
- 老年代触发后的使用过程:
- 1、扫描所有老年代对象,标记存活对象。
- 2、回收无标记的对象。
- 缺点: 每一次回收都会产生内存碎片,通常需要进行合并或标记出来方便下次直接分配。
2.3.3 永久代
内存永久保存的区域,主要存储Class和Meta(元数据)的信息。
- Class在被加载时就被放入永久代区域中,GC不会在主程序运行时对永久区进行回收,所以会导致OOM异常。
元数据空间: Java 8 引入代替永久代的内存空间,最大区别在于元数据空间是映射在实际内存上的,其大小也是限制在实际可用内存上的;而永久代则是映射在JVM的内存上,受JVM的限制。
2.4 垃圾回收算法
2.4.1 如何判断是否为垃圾?
- 引用计数法: 对象引用一次,引用计数器+1,当引用数为0或引用数是所有对象中最低的,则被GC回收。
- 可达性分析: 通过对一系列的“GC roots” 对象为起点进行搜索,当一个“GC roots” 和 一个对象之间没有可达路径,则该对象是不可达对象并进行标记,若第二次搜索标记仍然是不可达对象,则被GC回收。
2.4.2 有哪些GC算法?
- 标记清除算法(Mark-Sweep): 一种最基本的GC算法,分为两个阶段:标注和清除。其缺点是内存碎片化。
- 标注: 通过一次扫描进行标记可回收对象。
- 清除: 回收带有标记的对象。
- 复制算法(copying): 将内存分为等大的两份(主区域、备份区域),首先使用主区域,当主区域内存满后或不足以分配足够的空间时,将主区域进行一次标记清除回收,再将存活的对象复制到备份区域,并清理主区域。其缺点是可用内存减半,且在存活对象过多,复制算法效率下降。
- 标记整理算法(Mark-Compact): 分为三个阶段:标注、移动和清除。
- 标注: 标记可回收对象。
- 移动: 移动存活对象到内存的的一端。
- 清除: 清除存活对象存储区域外的所有区域。
- 分代收集算法: 主要是针对新生代、老年代和永久代的收集算法。
- 新生代: 采用复制算法
- 由于新生代的清除操作多于复制操作,所以一般划分一个较大的Edon区域和两个较小的Servivor空间,当进行GC时,将Eden区和其中一个Servivor空间存活的对象复制到另一个Servivor空间中。
- 老年代: 采用标记复制算法
- 当对象年龄到达15时,被清除于老年代。
- 永久代: 采用标记复制算法
- 主要收集 废弃常量 和 无用的类
- 新生代: 采用复制算法
2.5 Java的四种引用类型
- 强引用: 最常见于对象赋值变量,这个引用就是强引用,它不会被JVM回收,是造成OOM的主要原因。
- 软引用: 通过 SoftReference 类实现,对于软引用对象来说,只有在JVM内存不足时才会被回收,常见用于内存敏感的程序中。
- 弱引用: 通过 WeakRefrence 类实现,只要GC机制启动,该类引用就会被回收,常用于类初始化(例如类代码块)。
- 虚引用: 通过 PhantomRefrence 类实现,必须与引用队列联合使用,主要用于跟踪对象被回收的状态。
2.6 分代收集算法 和 分区收集算法的区别
2.6.1 分代收集算法
- 新生代-复制算法: 频繁发生GC且仅有少量存活对象时,选用复制算法,其付出成本较少。
- 老年代-标记整理算法: 对象存活率高,选用标记整理算法,效率更高
2.6.2 分区收集算法
- 分区算法是将一块内存空间分成连续不同的内存空间,每个小区间都可以独立使用,独立回收,可以控制一次性回收多个空间,根据目标停顿时间的不同,每次合理回收若干个小区间,从而减少一次GC所产生的停顿。
2.7 GC 垃圾收集器
Java 对新生代和老年代分别提供了不同的垃圾收集器。
- 新生代
- Serial(单线程复制算法): 一种最基本的垃圾收集器,是JDK 1.3.1 之前唯一的新生代GC器,执行时只使用一条线程或一个CPU并阻塞所有线程直到垃圾收集完成。因为其高效的特性,在限定单个CPU环境下,没有线程交互的开销,因此Serial依然是JVM在Client模式下的默认新生代收集器。
- ParNew(多线程Serial): 默认开启和CPU数量相同的线程数,可以通过
-XX:ParallelGCThreads
参数进行限制垃圾收集器的线程数。 - Parallel Scavenge(多线程自适应Serial): 高吞吐量环境下高效利用CPU时间进行垃圾回收,主要适用于后台运算且不需要过多交互的任务,自适应调节策略是其最大的特点。
- 老年代
- CMS(Concurrent mark sweep): 通过获取最短垃圾回收停顿时间,利用多线程的标记-清除算法进行垃圾回收。工作机制有四个阶段:
- 初始标记: 标记与GC roots直接关联的对象,速度极快,需要阻塞工作线程。
- 并发标记: 与用户线程并发执行跟踪GC roots操作
- 重新标记: 修正因用户程序运行而改变的标记,需要阻塞工作线程
- 并发清除: 当第一次标记与第二次标记都为可回收,则CMS清除当前可回收对象
- Serial Old(单线程标记整理算法): Serial 收集器的老年代版本,主要运行在 Client 默认的JVM老年代垃圾收集器。
- Parallel Old(多线程自适应Serial Old): Parallel Scavenge 收集器的老年代版本,在高吞吐环境下搭配 Parallel Scavenge 进行新/老年代的垃圾回收调节策略。
- CMS(Concurrent mark sweep): 通过获取最短垃圾回收停顿时间,利用多线程的标记-清除算法进行垃圾回收。工作机制有四个阶段:
- G1收集器: 改进了CMS,基于标记整理算法并且精确控制停顿时间,在保证高吞吐量的同时实现低停顿GC,具有有效时间内的最高垃圾回收效率。
- 1、将堆内存划分为大小固定的几个内存区域,并跟踪这几个区域的GC进度
- 2、维护一个优先级列表,根据允许的收集时间,优先回收垃圾最频繁产生的区域。
2.8 IO和NIO
2.8.1 阻塞IO模型
一种最传统的IO模型,即在读写过程中会发生阻塞现象
- 概念: 用户线程发出IO请求,内核查看数据就绪状态,若数据未就绪,则用户线程处于阻塞状态,用户线程交出CPU,当数据就绪时,内核拷贝数据到用户线程并返回结果到用户线程,用户线程解除阻塞状态。
- 例子:
data = socket.read
,若数据未就绪,就会一直阻塞在read方法。
2.8.2 非阻塞IO模型
- 概念: 当用户线程发出read操作后,内核检查数据就绪状态,若数据就绪则内核拷贝数据,若数据未就绪,则直接返回error结果,用户线程不断询问内核数据就绪状态,所以NIO模型会一直占用CPU。
- 例子:
while(true){ data = socket.read(); if( data != error ) break; }
- 缺点: CPU占用率高
2.8.3 多路复用IO模型
目前使用较多的IO模型,Java NIO 就是一种多路复用IO。
- 概念: 在多路复用IO模型中,会有一个内核线程不断轮询每个socket的状态,当socket 发出IO请求时,才调用 IO 操作。在Java NIO 中通过
selector.select()
轮询socket,若没有请求则阻塞在轮询状态。 - 使用场景: 适用于连接数较多的场景。
- 缺点: 若响应体过大,会阻塞其它IO请求处理,并且影响sokect轮询进度。
2.8.4 信号驱动IO模型
- 概念: 当用户线程发起一个IO请求,给对应的socket注册一个信号函数,然后用户线程继续执行,当内核数据就绪会发送一个信号给用户线程,当用户线程接收到信号后,利用信号函数的IO操作接口来实现读写操作。
2.8.5 异步IO模型
一种理想的IO模型。
- 概念: 当用户线程发起read请求后,无需等待数据返回,并发去做其它任务。而在内核角度,内核受到
asynchronous read
后,会立刻返回,说明 read 请求发起成功,因此不会发生阻塞状况,内核等待数据就绪完成后,将数据拷贝到用户线程并发送一个信号给用户线程。 - 使用: Java 7 中,提供了 AIO(Asynchronous IO)类。
- 优点: 用户线程在IO请求阶段和IO使用阶段都不需要阻塞线程,而是接受到内核发送的信号后可以直接使用数据。
2.9 Java IO包
主要是常用的字节流和字符流分支。
2.10 Java NIO包
NIO 主要有三大核心部分:Channel(通道)、Buffer(缓冲区)、Selector(选择器)。
NIO基于Channel与Buffer进行IO操作,数据总是从通道读取到缓冲区中或从缓冲区写入通道;而Selector监听多个Channel事件(例如连接、数据就绪),因此单个线程可以监听多个通道。
NIO 和 IO 之间最大区别是 【IO面向流,NIO面向缓冲区】
- ** NIO的缓冲区**
传统IO是从流中读取单个或多个字节,直至读取完所有字节,所以不能预处理流中的数据。
NIO缓冲区的设立是为了可以在缓冲区中灵活地预处理读取到的数据,当数据从通道读取到缓冲区后,可以在缓冲区中处理读取数据再执行获取数据操作,但处理数据时有两个问题需要处理:1、判断数据是否需要处理;2、读入新数据不覆盖未处理的数据。
- NIO的非阻塞
NIO的非阻塞是指在线程调用read或write操作时,会立刻在通道中获取当前可用数据或写入部分数据,若无数据可用,则返回空数据,无需等待有值数据,所以NIO可以用单独的线程管理多个IO通道。
- Java NIO类
2.10.1 Channel
Channel 和 IO中的Stream是同一级别的,只是Channel是双向的,Stream是单向的。
NIO中的Channel主要实现有:
- 1、FileChannel(文件IO)
- 2、DatagramChannel(UDP通道)
- 3、SocketChannel(TCP用户端通道)
- 4、ServerSocketChannel(TCP服务端通道)
2.10.2 Buffer
Buffer实际上是一个连续数组,任何读入或写入的数据都需要通过Buffer进行传输,但通道与通道之间不需要Buffer进行缓冲。
NIO中的Buffer主要实现有:
- 1、ByteBuffer
- 2、ShortBuffer
- 3、IntBuffer
- 4、LongBuffer
- 5、DoubleBuffer
- 6、FloatBuffer
- 7、CharBuffer
2.10.3 Selector
Selector能够检测多个注册的通道上是否发出IO请求,当有IO请求时,便获取请求事件并调用请求时间对应的响应方法。
2.11 JVM类加载机制
JVM类加载机制分为五个部分:
- 加载(Loading): 这个阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为读取这个类各种数据的方法区入口。(这里的Class对象可以是从压缩包中读取,也可以是动态代理类,也可以是其它文件生成)
- 验证(Verification): 这个阶段是为了确保Class文件的字节流包含的信息是符合当前JVM的要求。
- 准备(Preparation): 这个阶段是为了给类变量分配内存并初始化。(这里的初始化是JVM已经分配好的类型默认值,例如int类型的初始化值为 0)
- 解析(Resolution): 这个阶段是为了将常量池的符号引用替换为直接引用的过程。(就是将使用变量的位置都换成常量)
- 符号引用: 符号引用与虚拟机实现的布局无关,但符号引用的字面量形式必须符合JVM规范的Class文件格式。
- **直接引用:**引用目标在虚拟机中必须存在,直接引用的目标可以是是指向目标的指针,相对偏移量或是间接定位目标的句柄。
- 初始化(Initialization): 这个阶段是真正执行类中定义的Java程序代码,主要是执行类构造器
<client>
方法的过程。<client>
方法是编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的,JVM会保证子类构造器执行前,父类构造器完成执行,如果一个类中没有静态变量赋值也没有静态代码块,那么编译器不会为其生成<client>
方法。- 不执行类初始化的情况
- 1、子类引用父类的静态字段,只会触发父类的初始化
- 2、定义了对象数组
- 3、未直接引用定义常量的类
- 4、通过类名获取Class对象
- 5、调用Class.forName()加载指定类时,指定参数
initialize=false
- 6、调用了ClassLoader 默认的loadClass方法
JVM类的卸载机制分为两个部分:
- 使用(Using)
- 卸载(Unloading)
2.11.1 类加载器
JVM提供了三种类加载器:启动类加载器、扩展类加载器、应用程序类加载器、自定义类加载器。
- 启动类加载器(Bootstrap ClassLoader): 负责加载
JAVA_HOME\lib
目录中的,或通过-Xbootclasspath
指定路径中的,且被JVM认可(按文件识别,例如 rt.jar)的类。 - 扩展类加载器(Extension ClassLoader): 负责加载
JAVA_HOME\lib
目录中的,或通过java.ext.dirs
系统变量指定路径中的类库。 - 应用程序类加载器(Application ClassLoader): 负责加载用户路径(classpath)上的类库
- 自定义类加载器: JVM通过双亲委派模型进行类的加载,可以通过继承
java.lang.ClassLoader
实现自定义类加载器。
2.11.2 双亲委派模型
- 概念: 当一个类收到类加载请求时,首先将请求委派到父类加载器,每一层类加载器都会委派到父类加载器,所以最终所有的类加载请求都会到达启动类加载器,当父类加载器响应无法处理请求(自身加载路径下未找到所需加载的Class)时,子类加载器才尝试自行加载。
- 优点: 保证了不同的类加载器最终获得同一个Object对象。
2.11.3 OSGI(动态模型系统)
OSGI 提供了在多种网络设备中无需重启的动态改变构造的功能,可以实现模块级的热插拔功能,在程序升级更新时,可以只停用、重新安装、启动程序部分模块,但在提供模块化功能的同时,也会额外引入高复杂度,因为不遵循双亲委派模型。
相关文章:
Java技术整理(1)—— JVM篇
1、什么是JVM? JVM是一个可运行Java代码的虚拟计算机,包括一套字节码指令集,一组寄存器,一个栈,一个垃圾回收,堆和一个存储方式栈。JVM 是运行在操作系统之上,并不与操作系统直接交互。 2、运行…...

bug解决:AssertionError: No inf checks were recorded for this optimizer.
这真的是最恶心的一个error(比网络回传找哪层没有传播到还要恶心!),找了好久的问题所在之处,最后偶然发现了这篇文章: 解决pytorch半精度amp训练nan问题 - 知乎 然后发现自己用的混合精度训练,发…...
Django笔记之数据库查询优化汇总
1、性能方面 1. connection.queries 前面我们介绍过 connection.queries 的用法,比如我们执行了一条查询之后,可以通过下面的方式查到我们刚刚的语句和耗时 >>> from django.db import connection >>> connection.queries [{sql: S…...

JVM内存区域
预备 为了更好的理解类加载和垃圾回收,先要了解一下JVM的内存区域(如果没有特殊说明,都是针对的是 HotSpot 虚拟机。)。 Java 源代码文件经过编译器编译后生成字节码文件,然后交给 JVM 的类加载器,加载完…...

某行业CTF一道流量分析题
今晚看了一道题,记录学习下。 给了一个hacktrace.pcapng,分析主要内容如下: 上传两个文件,一个mouse.m2s,一个mimi.zip,将其导出。 mimi.zip中存放着secret.zip和key.pcapng 不过解压需要密码ÿ…...

【Kafka】1.Kafka简介及安装
目 录 1. Kafka的简介1.1 使用场景1.2 基本概念 2. Kafka的安装2.1 下载Kafka的压缩包2.2 解压Kafka的压缩包2.3 启动Kafka服务 1. Kafka的简介 Kafka 是一个分布式、支持分区(partition)、多副本(replica)、基于 zookeeper 协调…...

Kafka API与SpringBoot调用
文章目录 首先需要命令行创建一个名为cities的主题,并且创建该主题的订阅者。 1、使用Kafka原生API1.1、创建spring工程1.2、创建发布者1.3、对生产者的优化1.4、批量发送消息1.5、创建消费者组1.6 消费者同步手动提交1.7、消费者异步手动提交1.8、消费者同异步手动…...
JavaScript构造函数和类的区别
原文 构造函数 没有显式的创建对象创建对象时使用new操作符。所有属性和方法赋值给this对象。没有return语句按照惯例,构造函数的方法名首字母应该使用大写字母,用于区分普通函数,其实构造函数也是函数,其主要功能是用来创建对象…...

Spring与Spring Bean
Spring 原理 它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可 以和其他的框架无缝整合。 Spring 特点 轻量级 控制反转 面向切面 容器 框架集合 Spring 核心组件 Spring 总共有十几个组件核心容器(Spring core) S…...

并发相关面试题
巩固基础,砥砺前行 。 只有不断重复,才能做到超越自己。 能坚持把简单的事情做到极致,也是不容易的。 如何理解volatile关键字 在并发领域中,存在三大特性:原子性、有序性、可见性。volatile关键字用来修饰对象的属性…...

Hadoop+Python+Django+Mysql热门旅游景点数据分析系统的设计与实现(包含设计报告)
系统阐述的是使用热门旅游景点数据分析系统的设计与实现,对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计,描述,实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体…...
php中nts和ts
PHP语言解析器:官方提供了2种类型的版本,线程安全(TS)版和非线程安全(NTS)版 TS: TS(Thread-Safety)即线程安全,多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时进行数据加锁保护,其他线程不能同时进行访…...

设计模式之责任链模式【Java实现】
责任链(Chain of Resposibility) 模式 概念 责任链(chain of Resposibility) 模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者 通过前一对象记住其下一个对象的引用而连成一条…...
Android 12.0 系统systemui状态栏下拉左滑显示通知栏右滑显示控制中心模块的流程分析
1.前言 在android12.0的系统rom定制化开发中,在系统原生systemui进行自定义下拉状态栏布局的定制的时候,需要在systemui下拉状态栏下滑的时候,根据下滑坐标来 判断当前是滑出通知栏还是滑出控制中心模块,所以就需要根据屏幕宽度,来区分x坐标值为多少是左滑出通知栏或者右…...

服务器安装JDK
三种方法 方法一: 方法二: 首先登录到Oracle官网下载JDK JDK上传到服务器中,记住文件上传的位置是在哪里(我放的位置在/www/java),然后看下面指示进行安装 方法三: 首先登录到Oracle官网下载…...
cpu查询
1.mpstat查看系统cpu状况 mpstat 1 1或者mpstat -P ALL查看每个cpu使用状态,(用户态cpu是用来,内核态cpu使用率,等待IO使用率) 2.vmstat 可以查看系统运行任务数(正在cpu运行进程和就绪队列进程࿰…...

【muduo】关于自动增长的缓冲区
目录 为什么需要缓冲区自动增长的缓冲区buffer数据结构buffer类 写详细比较费时间,就简单总结下。 总结自Linux 多线程服务端编程:使用 muduo C 网络库 Muduo网络编程: IO-multiplexnon-blocking 为什么需要缓冲区 Non-blocking IO 的核心…...

原型和原型链理解
这个图大概能概括原型和原型链的关系 1.对象都是通过 _proto_ 访问原型 2.原型都是通过constructor 访问构造函数 3.原型是构造函数的 prototype 4.原型也是对象实例 也是通过 _proto_ 访问原型(Object.prototype) 5.Object.prototype的原型通过 _proto_ 访问 为null 那么…...

CSS:弹性盒子模型详解(用法 + 例子 + 效果)
目录 弹性盒子模型flex-direction 排列方式 主轴方向换行排序控制子元素缩放比例缩放是如何实现的? 控制子元素的对其方式justify-content 横向 对齐方式align-items 纵向 对齐方式 align-content 多行 对齐方式 弹性盒子模型 flex-direction 排列方式 主轴方向 f…...

分类预测 | Matlab实现基于MIC-BP最大互信息系数数据特征选择算法结合BP神经网络的数据分类预测
分类预测 | Matlab实现基于MIC-BP最大互信息系数数据特征选择算法结合BP神经网络的数据分类预测 目录 分类预测 | Matlab实现基于MIC-BP最大互信息系数数据特征选择算法结合BP神经网络的数据分类预测效果一览基本介绍研究内容程序设计参考资料 效果一览 基本介绍 Matlab实现基于…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...

GraphRAG优化新思路-开源的ROGRAG框架
目前的如微软开源的GraphRAG的工作流程都较为复杂,难以孤立地评估各个组件的贡献,传统的检索方法在处理复杂推理任务时可能不够有效,特别是在需要理解实体间关系或多跳知识的情况下。先说结论,看完后感觉这个框架性能上不会比Grap…...

云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...
Ansible+Zabbix-agent2快速实现对多主机监控
ansible Ansible 是一款开源的自动化工具,用于配置管理(Configuration Management)、应用部署(Application Deployment)、任务自动化(Task Automation)和编排(Orchestration…...
RK3568项目(七)--uboot系统之外设与PMIC详解
目录 一、引言 二、按键 ------>2.1、按键种类 ------------>2.1.1、RESET ------------>2.1.2、UPDATE ------------>2.1.3、PWRON 部分 ------------>2.1.4、RK809 PMIC ------------>2.1.5、ADC按键 ------------>2.1.6、ADC按键驱动 ------…...