当前位置: 首页 > news >正文

JVM的小知识总结

加载时jvm做了这三件事:
1)通过一个类的全限定名来获取该类的二进制字节流

什么是全限定类名?

就是类名全称,带包路径的用点隔开,例如: java.lang.String。
即全限定名 = 包名+类型

非限定类名也叫短名,就是我们平时说的类名,不带包的,例如:String
2)将这个字节流的静态存储结构转化为方法区运行时数据结构
3)在内存堆中生成一个代表该类的java.lang.Class对象,作为该类数据的访问入口

2.验证

验证、准备、解析这三步可以看做是一个连接的过程,将类的字节码连接到JVM的运行状态之中
验证是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,不会威胁到jvm的安全
验证主要包括以下几个方面的验证:
1)文件格式的验证,验证字节流是否符合Class文件的规范,是否能被当前版本的虚拟机处理
2)元数据验证,对字节码描述的信息进行语义分析,确保符合java语言规范
3)字节码验证 通过数据流和控制流分析,确定语义是合法的,符合逻辑的
4)符号引用验证 这个校验在解析阶段发生

3.准备
为类的静态变量分配内存,初始化为系统的初始值。对于final static修饰的变量,直接赋值为用户的定
义值。如下面的例子:这里在准备阶段过后的初始值为0,而不是7:


4.解析
解析是将常量池内的符号引用转为直接引用(如物理内存地址指针)


5.初始化
到了初始化阶段,jvm才真正开始执行类中定义的java代码
1)初始化阶段是执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译器自动收集
类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
2)当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先触发其父类的初始化。
3)虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。

流程图

小插曲:猜猜这东西执行结果是什么?


public class ParentClass {private int parentX;public ParentClass() {setX(100);}public void setX(int x) {parentX = x;}
}public class ChildClass extends ParentClass{private int childX = 1;public ChildClass() {}@Overridepublic void setX(int x) {super.setX(x);childX = x;System.out.println("ChildX 被赋值为 " + x);}public void printX() {System.out.println("ChildX = " + childX);}}public class TryInitMain {public static void main(String[] args) {ChildClass cc = new ChildClass();cc.printX();}
}

当然是1啦,子类构造函数执行才会真的初始化里面的值,道理不难,但是要真的理解

另一个小插曲


public class ParseFile4OOM {public static void main(String[] args) {List<Map<String, String>> lst = new ArrayList<>();for (int i = 0; i < 100000; i++) {Map<String, String> map = new HashMap<>(3);map.put("Column1".intern(), "Content1".intern());map.put("Column2".intern(), "Content2".intern());map.put("Column3".intern(), "Content3".intern());lst.add(map);}Map<String, List<Map<String, String>>> contentCache = new HashMap<>();contentCache.put("contents".intern(), lst);}
}

 JDK8引入了 String 常量池。同时,Hashmap 在这个业务场景下,容积是固定的,所以,就不应该给它多分配空间,就固定死为 3。

new 对象的过程

虚拟机遇到一条new指令时,首先检查是否被类加载器加载,如果没有,那必须先执行相应的类加载过
程。类加载就是把class加载到JVM的运行时数据区的过程。

什么意思?

class Lava { 
private int speed = 5; // 5 kilometers per hour 
void flow() { 
} 
}class Volcano { 
public static void main(String[] args) { 
Lava lava = new Lava(); 
lava.flow(); 
} 
}

为了运行这个程序,你以某种方式把“Volcano”传给了jvm。有了这个名字,jvm找到了这个类文件(Volcano.class)并读入,它从类文件提取了类型信息并放在了方法区中,通过解析存在方法区中的字节码,jvm激活了main()方法,在执行时,jvm保持了一个指向当前类(Volcano)常量池的指针

注意jvm在还没有加载Lava类的时候就已经开始执行了。正像大多数的jvm一样,不会等所有类都加载了以后才开始执行,它只会在需要的时候才加载。

main()的第一条指令告知jvm为列在常量池第一项的类分配足够的内存。jvm使用指向Volcano常量池的指针找到第一项,发现是一个对Lava类的符号引用,然后它就检查方法区看lava是否已经被加载了。

检查加载
首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查类是否已经被加载、解
析和初始化过。

符号引用:以一组符号来描述所引用的目标。符号引用可以是任何形式的字面量,JAVA在编译的
时候一个每个java类都会被编译成一个class文件,但在编译的时候虚拟机并不知道所引用类的地
址(实际地址),就用符号引用来代替,而在类的解析阶段就是为了把这个符号引用转化成为真正的
地址的阶段。
假设People类被编译成一个class文件时,如果People类引用了Tool类,但是在编译时People类并
不知道引用类的实际内存地址,因此只能使用符号引用(org.simple.Tool)来代替。而在类装载
器装载People类时,此时可以通过虚拟机获取Tool类的实际内存地址,因此便可以既将符号
org.simple.Tool替换为Tool类的实际内存地址。

分配内存
完成类的加载检查后,虚拟机将为新生对象分配内存。为对象分配空间的任务等同于把一块确定大小的
内存从Java堆中划分出来。

内存从Java堆中划分出来。
指针碰撞
如果Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个
指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等
的距离,这种分配方式称为—指针碰撞。
空闲列表
如果Java堆中的内存并不是规整的,已使用的内存和空闲的内存相互交错,那就没有办法简单地进行指
针碰撞了,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块
足够大的空间划分给对象实例,并更新列表上的记录,这种分配方式称为—空闲列表。
选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整
理功能决定。

并发安全
除如何划分可用空间之外,还有另外一个需要考虑的问题是对象创建在虚拟机中是非常频繁的行为,即
使是仅仅修改一个指针所指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象A分配
内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。

内存空间初始化
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值。这一步操作保证了对象的实例字段
在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。(如int值为
0,boolean值为false等等)。
设置
完成空间初始化后,虚拟机对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的
元数据信息(Java classes在Java hotspot VM内部表示为类元数据)、对象的哈希码、对象的GC分代年
龄等信息。这些信息存放在对象的对象头之中。
对象初始化
在以上工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。但从Java程序的视角来看,
对象创建才刚刚开始,所有的字段都还为零值。所以,一般来说,执行new指令之后会接着把对象按照
程序员的意愿进行初始化(构造方法),这样一个真正可用的对象才算完全产生

那么问题来了,对象的内存分配在堆上,那么一个全局变量赋值给两个局部变量会出现互相影响的情况吗?

对象在Java中是分配在堆上的,但每个线程在操作对象时,操作的是对象的引用而不是对象本身。因此,即使对象是在堆上分配的,各个线程分别操作对象引用,不会直接影响到堆上的对象。

让我们解释一下:

  1. 对象引用: 在Java中,变量存储的是对象的引用,而不是对象本身。当你创建一个对象时,实际上在堆上分配了内存,并且变量存储的是指向该对象的引用。多个变量可以引用同一个对象。

  2. 线程操作: 当你在不同的线程中将对象引用赋给不同的局部变量时,每个线程操作的是各自的局部变量和引用:虽然 localVar1localVar2 都引用了 globalObject,但它们是独立的局部变量,互不影响。

 总的来说,尽管对象在堆上分配,但在多线程环境中,线程之间的独立性和引用的独立性通常由于每个线程操作自己的局部变量而得以保持,因此不会产生直接的影响。线程1和线程2的操作会影响到 globalObject 引用所指向的对象,最终的结果会体现在 globalObject 对象上。

GC的流程是怎么样的

说到GC垃圾回收,首先要知道什么是“垃圾”,垃圾就是没有用的对象,那么怎样判定一个对象是不是垃
圾(能不能被回收)?Java 虚拟机中使用一种叫作可达性分析的算法来决定对象是否可以被回收。

可达性分析就通过一组名为”GC Root"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径
称为引用链,最后通过判断对象的引用链是否可达来决定对象是否可以被回收。

GC Root指的是:
Java 虚拟机栈(局部变量表)中的引用的对象。也就是正在运行的方法中的局部变量所引用的对象
方法区中静态引用指向的对象。也就是类中的static修饰的变量所引用的对象
方法区中常量引用的对象。
仍处于存活状态中的线程对象。
Native 方法中 JNI 引用的对象。

优点
可达性分析可以解决引用计数器所不能解决的循环引用问题。即便对象a和b相互引用,只要从GC Roots
出发无法到达a或者b,那么可达性分析便不会将它们加入存活对象合集之中。

缺点
在多线程环境下,其他线程可能会更新已经访问过的对象中的引用,从而造成误报(将引用设置为null)或
者漏报(将引用设置为未被访问过的对象)。误报并没有什么伤害,Java虚拟机至多损失了部分垃圾回收的
机会。漏报则比较麻烦,因为垃圾回收器可能回收事实上仍被引用的对象内存。 一旦从原引用访问已经
被回收了的对象,则很有可能会直接导致Java虚拟机崩溃。

垃圾回收算法
在标记出对象是否可被回收后,接下来就需要对可回收对象进行回收。基本的回收算法有:标记-清理、
标记-整理与复制算法。
标记清除算法
从”GC Roots”集合开始,将内存整个遍历一次,保留所有可以被 GC Roots 直接或间接引用到的对象,
而剩下的对象都当作垃圾对待并回收,过程分为 标记 和 清除 两个步骤。

优点:实现简单,不需要将对象进行移动。
缺点:这个算法需要中断进程内其他组件的执行(stop the world),并且可能产生内存碎片,提
高了垃圾回收的频率。


标记整理算法
与标记-清除不同的是它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。最
后,清理边界外所有的空间。
优点:这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。
缺点:所谓压缩操作,仍需要进行局部对象移动,所以一定程度上还是降低了效率。

简单说就是把所有数据压缩到内存条一端

复制算法
将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中。之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收

那么作为一个开发者,我们知道了GC的流程应该学到什么呢?

避免频繁GC的目标之一就是减少标记阶段和清理阶段的发生次数,以降低对系统性能的影响。

以下是一些使用对象的最佳实践,可以帮助避免频繁的垃圾回收:

  1. 对象池(Object Pooling): 通过使用对象池,可以重复使用已经存在的对象,而不是频繁地创建和销毁对象。这样可以减少新生代的垃圾回收频率,因为不需要频繁分配和释放内存。

  2. 缓存大对象: 对于一些大对象,特别是那些生命周期较长且频繁使用的对象,考虑进行缓存而不是频繁地创建和销毁。这有助于减少老年代的垃圾回收频率。

  3. 限制对象的作用域: 将对象的作用域限制在其真正需要的地方,避免对象在不需要的时候仍然被引用。对象的生命周期越短,它占用的内存就越容易被及时回收。

  4. 谨慎使用Finalizer: 避免过度依赖finalize方法。虽然Java提供了finalize方法供对象进行资源释放,但过度依赖它可能导致不可预测的垃圾回收行为。

  5. 合理设置堆大小: 根据应用程序的需求和性能特征,合理设置堆大小,避免出现频繁的Full GC。

  6. 合理选择垃圾回收器: 根据应用程序的性能需求和特性,选择合适的垃圾回收器。不同的垃圾回收器有不同的特点和适用场景。

  7. 使用软引用和弱引用: 对于一些可以被回收的对象,可以考虑使用软引用或弱引用,以便在内存不足时更容易被回收。

Java中对象如何晋升到老年代? 

实际上有四种情况可能会导致对象晋升老年代:
大对象直接进入老年代
年龄超过阈值
动态对象年龄判定
年轻代空间不足

那么进入老年代的对象一定会被回收嘛?

不一定。虽然老年代中的对象通常是存活时间较长的对象,但并不是所有进入老年代的对象都会被回收。老年代中的对象会随着应用程序的执行而逐渐积累,而垃圾回收器会根据其算法和策略在适当的时候尝试回收不再被引用的对象。

老年代中的垃圾回收通常是由Full GC(Full Garbage Collection)触发的,Full GC 会对整个堆进行回收,包括新生代和老年代。Full GC 的触发条件通常是在老年代没有足够空间分配一个大对象,或者老年代的碎片化导致无法找到足够的连续空间来分配对象。

在进行 Full GC 时,垃圾回收器会标记并清理不再被引用的对象,释放它们占用的内存。被标记为不再被引用的老年代对象将会被回收,但并非所有老年代中的对象都会被回收。

判断对象是否被回收,有哪些GC算法?

是否掌握可达性分析法了解如何确定对象是否可被回收,从而避免程序内存泄露问题

而除了可达性分析法之外,还有被淘汰的引用计数算法:
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就
减1;任何时刻计数器为0的对象就是不可能再被使用的。

目前主流的java虚拟机都摒弃掉了这种算法,最主要的原因是它很难解决对象之间相互循环引用的问
题,尽管该算法执行效率很高。

那么什么是 对象之间相互循环引用?

简单的例子两个单例类之间直接互相引用 

如果你发现两个单例类需要相互引用,可能需要重新考虑你的设计。以下是一些可能的解决方案:

  1. 合并成一个单例类: 如果两个单例类之间存在强耦合,可能它们应该被设计成一个单例类,以减少依赖关系。

  2. 通过接口/抽象类解耦: 如果两个单例类确实需要相互引用,可以考虑引入接口或抽象类,将它们的关系抽象出来,降低直接依赖。

  3. 使用依赖注入: 考虑通过依赖注入的方式来解耦,将一个单例类的实例注入到另一个单例类中,而不是直接在类内部进行引用。

  4. 重新评估设计: 如果发现两个单例类之间的关系过于复杂,可能需要重新评估系统的设计,考虑是否有更清晰、更简单的方式来组织代码。

 

Class会不会回收?用不到的Class怎么回收?

Java 虚拟机理论上会回收Class,Class要被回收,条件比较"苛刻",必须同时满足以下的条件:
1、该类的所有实例都已经被回收,即 Java 堆中不存在该类及其任何派生子类的实例
2、加载该类的类加载器已经被回收
3、该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
Java 虚拟机允许对满足上述三个条件的无用类进行回收,但并不是说必然被回收,仅仅是允许而已

JVM模型

相关文章:

JVM的小知识总结

加载时jvm做了这三件事&#xff1a; 1&#xff09;通过一个类的全限定名来获取该类的二进制字节流 什么是全限定类名&#xff1f; 就是类名全称&#xff0c;带包路径的用点隔开&#xff0c;例如: java.lang.String。 即全限定名 包名类型 非限定类名也叫短名&#xff0c;就…...

深入理解JVM虚拟机第二十六篇:详解JVM当中的虚方法和非虚方法,并从字节码指令的角度去分析虚方法和非虚方法

😉😉 学习交流群: ✅✅1:这是孙哥suns和树哥给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783824 📚​​​​​​​📚 微信:DashuDeveloper拉你进微信群,免费领取! 一:非虚方法和虚方法 方法…...

ElasticSearch的日志配置

ElasticSearch默认情况下使用Log4j2来记录日志&#xff0c;日志配置文件的路径为$ES_HOME/config/log4j2.properties&#xff0c;配置方法见Log4j2的官方文档。 参考path-settings&#xff0c;通过指定path.logs&#xff0c;可以指定日志文件的保存路径。 在日志配置文件$ES_…...

SQL Injection (Blind)`

SQL Injection (Blind) SQL Injection (Blind) SQL盲注&#xff0c;是一种特殊类型的SQL注入攻击&#xff0c;它的特点是无法直接从页面上看到注入语句的执行结果。在这种情况下&#xff0c;需要利用一些方法进行判断或者尝试&#xff0c;这个过程称之为盲注。 盲注的主要形式有…...

NX二次开发UF_CURVE_ask_trim 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_trim Defined in: uf_curve.h int UF_CURVE_ask_trim(tag_t trim_feature, UF_CURVE_trim_p_t trim_info ) overview 概述 Retrieve the current parameters of an a…...

linux的netstat命令和ss命令

1. 网络状态 State状态LISTENING监听中&#xff0c;服务端需要打开一个socket进行监听&#xff0c;侦听来自远方TCP端口的连接请求ESTABLISHED已连接&#xff0c;代表一个打开的连接&#xff0c;双方可以进行或已经在数据交互了SYN_SENT客户端通过应用程序调用connect发送一个…...

python:傅里叶分析,傅里叶变换 FFT

使用python进行傅里叶分析&#xff0c;傅里叶变换 FFT 的一些关键概念的引入&#xff1a; 1.1.离散傅里叶变换&#xff08;DFT&#xff09; 离散傅里叶变换(discrete Fourier transform) 傅里叶分析方法是信号分析的最基本方法&#xff0c;傅里叶变换是傅里叶分析的核心&…...

云原生系列Go语言篇-编写测试Part 2

基准测试 确定代码是快或慢非常复杂。我们不用自己计算&#xff0c;应使用Go测试框架内置的基准测试。下面来看​​第15章的GitHub代码库​​sample_code/bench目录下的函数&#xff1a; func FileLen(f string, bufsize int) (int, error) {file, err : os.Open(f)if err ! …...

CMake Error:No targets specified and no makefile found

在适用cmake构建项目的时候&#xff0c;突然遇到了这个报错 Make Error at CMakeLists.txt:1 (project): VERSION not allowed unless CMP0048 is set to NEW – Configuring incomplete, errors occurred! make: *** No targets specified and no makefile found. Stop. CMake…...

常见树种(贵州省):019滇白珠、杜茎山、苍山越桔、黄背越桔、贵州毛柃、半齿柃、钝叶柃、细枝柃、细齿叶柃木、土蜜树、山矾、胡颓子、檵木

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、滇白珠…...

java - 定时器

一、什么是定时器 定时器是指可以通过 Java 中的 Timer 类和 TimerTask 类所提供的功能来实现定期执行某些任务的工具。 标准库中提供了一个 Timer 类 . Timer 类的核心方法为 schedule . schedule 包含两个参数 . 第一个参数指定即将要执行的任务代码 , 第二个参数指定多…...

jQuery【菜单功能、淡入淡出轮播图(上)、淡入淡出轮播图(下)、折叠面板】(五)-全面详解(学习总结---从入门到深化)

目录 菜单功能 淡入淡出轮播图(上) 淡入淡出轮播图(下) 折叠面板 菜单功能 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><…...

攻防非对称问题| 当前企业面临的网络攻防非对称问题及其解决途径

随着信息技术的不断发展&#xff0c;网络已经成为我们日常生活和商业活动中不可或缺的一部分。然而&#xff0c;随之而来的是网络安全问题的不断升级。网络攻防非对称问题是当前亟待解决的一个复杂而严峻的挑战。其主要的表现是攻击成本远低于防御成本以及相同投入带来的攻击能…...

Java多线程二-线程安全

1、线程安全问题 多个线程&#xff0c;同时操作同一个共享资源的时候&#xff0c;可能会出现业务安全问题。 2、实例&#xff1a;取钱的线程安全问题 2.1、场景 小明和小红是夫妻&#xff0c;他们有个共同账户&#xff0c;余额是十万元&#xff0c;如果两人同时取钱并且各自取…...

Rust个人学习之结构体

第一反应&#xff0c;Rust结构体跟python的很像&#xff0c;不知道感觉对不对&#xff1b; 书中提到第一反应&#xff0c;Rust结构体跟python的很像&#xff0c;不知道感觉对不对&#xff1b; 书中提到&#xff1a;结构体是一种自定义数据类型&#xff0c;它允许命名多个相关的…...

kafka详细讲解与安装

Kafka是一种分布式流处理平台&#xff0c;具有高吞吐量、可扩展性和容错性。它最初由LinkedIn开发&#xff0c;现已成为Apache软件基金会的顶级项目。Kafka广泛应用于实时数据流处理、日志收集、消息队列等场景。 以下是关于Kafka的简要讲解和安装步骤&#xff1a; 一、Kafka…...

在我国干独立游戏开发有多难?

游戏独立开发在中国&#xff0c;一直以来都是一条充满挑战的道路。尽管有着无限的激情和创意&#xff0c;但面对市场、资金、政策等多方面的困难&#xff0c;许多独立开发者在这条路上艰难前行。 首先&#xff0c;市场竞争激烈是中国游戏独立开发者面临的首要挑战。随着游戏产…...

不可错过的网上宝藏:2023年必看的顶级资源大盘点!

亲爱的“AI uTools”读者们&#xff0c;大家好&#xff01; 在这个信息爆炸的时代&#xff0c;互联网上充满了无数的资源&#xff0c;但如何从这海量信息中挑选出真正有用的宝藏呢&#xff1f;今天&#xff0c;我为大家精心挑选了一系列优质网站资源&#xff0c;涵盖了从文本处…...

日本服务器访问速度和带宽有没有直接关系?

​  对于许多网站和应用程序来说&#xff0c;服务器的访问速度是至关重要的。用户希望能够快速加载页面、上传和下载文件&#xff0c;而这些都与服务器的带宽有关。那么&#xff0c;日本服务器的访问速度和带宽之间是否存在直接关系呢? 我们需要了解什么是带宽。带宽是指网络…...

[vxe-table] vxe-table-column配合v-if导致列样式与位置错乱

<vxe-table-column v-if"pageInfo.id 4 ||pageInfo.id 8" title"上报类型" width"100" key1><template v-slot"{row}"><span>咨询工具</span></template> </vxe-table-column>//或者<vxe-ta…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

C++_哈希表

本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、基础概念 1. 哈希核心思想&#xff1a; 哈希函数的作用&#xff1a;通过此函数建立一个Key与存储位置之间的映射关系。理想目标&#xff1a;实现…...

怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)

+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考

目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候&#xff0c;显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...

「Java基本语法」变量的使用

变量定义 变量是程序中存储数据的容器&#xff0c;用于保存可变的数据值。在Java中&#xff0c;变量必须先声明后使用&#xff0c;声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例&#xff1a;声明与初始化 public class VariableDemo {publi…...