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

JVM 栈帧结构详解

在 Java 虚拟机(JVM)中,栈帧(Stack Frame)是用于支持方法调用和方法执行的关键数据结构。每个方法从调用开始到执行完成,都对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。本文将详细介绍 JVM 栈帧的结构及其组成部分。

1 栈帧的组成

每个栈帧包含以下几个主要部分:

  • 局部变量表(Local Variables Table)
  • 操作数栈(Operand Stack)
  • 动态链接(Dynamic Linking)
  • 方法返回地址(Return Address)
  • 附加信息(Additional Information)

2 局部变量表(Local Variables Table)

局部变量表用于存储方法中的局部变量和方法参数。在 Java 源代码被编译成字节码文件时,局部变量表的最大容量就已经确定。

2.1 示例代码

考虑以下代码片段:

public class LocalVariablesTable {private void write(int age) {String name = "沉默王二";}
}

write() 方法有一个参数 age 和一个局部变量 name

2.2 使用 jclasslib 查看字节码

使用 jclasslib 工具查看编译后的字节码文件 LocalVariablesTable.class,可以看到 write() 方法的 Code 属性中,Maximum local variables 的值为 3。
在这里插入图片描述

理论上,局部变量表的最大容量应该是 2(一个 age,一个 name),但实际值为 3。这是因为非静态方法的局部变量表中,第 0 个位置存储的是调用该方法的对象引用 this。因此,调用 write(18) 实际上是调用 write(this, 18)

查看 Code 属性中的 LocalVariableTable,可以看到详细信息:
在这里插入图片描述

  • 第 0 个是 this,类型为 LocalVariablesTable 对象。
  • 第 1 个是方法参数 age,类型为整型 int
  • 第 2 个是方法内部的局部变量 name,类型为字符串 String

2.3 局部变量表的大小与作用域

局部变量表的大小不仅取决于局部变量的数量,还与变量的类型和作用域有关。当一个局部变量的作用域结束时,它占用的局部变量表位置会被后续的局部变量取代。

考虑以下代码:

public static void method() {// ①if (true) {// ②String name = "沉默王二";}// ③if (true) {// ④int age = 18;}// ⑤
}

在这里插入图片描述

  • method() 方法的局部变量表大小为 1,因为它是静态方法,不需要添加 this 作为局部变量表的第一个元素。
  • 在 ② 处,局部变量 name 的作用域开始,局部变量表的大小为 1。
  • 在 ③ 处,局部变量 name 的作用域结束。
  • 在 ④ 处,局部变量 age 的作用域开始,局部变量表的大小为 1。
  • 在 ⑤ 处,局部变量 age 的作用域结束。

《Effective Java》中的第 57 条建议:

将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性。

为了节省栈帧的内存空间,局部变量表中的槽是可以重用的。合理的作用域设计有助于提高程序性能。

2.4 局部变量表的槽(Slot)

局部变量表的容量以槽(slot)为最小单位,一个槽可以容纳一个 32 位的数据类型(如 int)。对于占用 64 位的数据类型(如 doublelong),会占用两个紧挨着的槽。

考虑以下代码:

public void slot() {double d = 1.0;int i = 1;
}

使用 jclasslib 查看 slot() 方法的字节码,可以看到 Maximum local variables 的值为 4。
在这里插入图片描述

为什么是 4 呢?加上 this 也只有 3 个变量。查看 LocalVariableTable 可以看到,变量 i 的下标为 3,这意味着变量 d 占了两个槽。
在这里插入图片描述

3 操作数栈(Operand Stack)

操作数栈是 JVM 栈帧中的一个重要组成部分,用于在方法执行过程中存储操作数和中间计算结果。与局部变量表类似,操作数栈的最大深度在编译时就已经确定,并写入到方法表的 Code 属性的 maximum stack size 中。

3.1 示例代码

考虑以下代码片段:

public class OperandStack {public void test() {add(1, 2);}private int add(int a, int b) {return a + b;}
}

OperandStack 类包含两个方法:test()add()test() 方法调用了 add() 方法,并传递了两个参数。

3.2 使用 jclasslib 查看字节码

使用 jclasslib 工具查看 test() 方法的字节码,可以看到 maximum stack size 的值为 3。
在这里插入图片描述

这是因为调用成员方法时,会将 this 和所有参数压入操作数栈中。调用完毕后,this 和参数会依次出栈。通过 Bytecode 面板可以查看对应的字节码指令:
在这里插入图片描述

  • aload_0:将局部变量表中下标为 0 的引用类型的变量(即 this)加载到操作数栈中。
  • iconst_1:将整数 1 加载到操作数栈中。
  • iconst_2:将整数 2 加载到操作数栈中。
  • invokevirtual:调用对象的成员方法。
  • pop:将栈顶的值出栈。
  • return:为 void 方法的返回指令。

3.3 add() 方法的字节码指令

再来看一下 add() 方法的字节码指令:
在这里插入图片描述

  • iload_1:将局部变量表中下标为 1 的 int 类型变量(即参数 a)加载到操作数栈上(下标为 0 的是 this)。
  • iload_2:将局部变量表中下标为 2 的 int 类型变量(即参数 b)加载到操作数栈上。
  • iadd:用于 int 类型的加法运算。
  • ireturn:为返回值为 int 的方法返回指令。

3.4 数据类型匹配

操作数栈中的数据类型必须与字节码指令匹配。例如,iadd 指令只能用于整型数据的加法运算。在执行 iadd 指令时,栈顶的两个数据必须是 int 类型,不能出现一个 long 型和一个 double 型的数据进行 iadd 命令相加的情况。

4 动态链接(Dynamic Linking)

动态链接是 JVM 栈帧中的一个重要概念,它允许在运行时根据对象的实际类型来解析方法调用。每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,这个引用用于支持方法调用过程中的动态链接。

4.1 运行时常量池与方法区

在深入理解动态链接之前,我们需要了解两个关键概念:

  1. 方法区(Method Area)

    • 方法区是 JVM 的一个运行时内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量以及即时编译器编译后的代码等。
    • 不同版本的 JDK 对方法区的实现可能有所不同,但其主要功能是相同的。
  2. 运行时常量池(Runtime Constant Pool)

    • 运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。
    • 在类加载后,这些字面量和符号引用会被加载到运行时常量池中。

4.2 示例代码

考虑以下代码片段:

public class DynamicLinking {static abstract class Human {protected abstract void sayHello();}static class Man extends Human {@Overrideprotected void sayHello() {System.out.println("男人哭吧哭吧不是罪");}}static class Woman extends Human {@Overrideprotected void sayHello() {System.out.println("山下的女人是老虎");}}public static void main(String[] args) {Human man = new Man();Human woman = new Woman();man.sayHello();woman.sayHello();man = new Woman();man.sayHello();}
}

在这段代码中,ManWoman 类继承了 Human 类,并重写了 sayHello() 方法。运行结果如下:

男人哭吧哭吧不是罪
山下的女人是老虎
山下的女人是老虎

从面向对象编程的角度来看,这个结果是符合预期的。manwoman 的引用类型都是 Human,但它们分别指向 ManWoman 对象。之后,man 被重新指向 Woman 对象。

4.3 字节码分析

使用 jclasslib 工具查看 main 方法的字节码指令:
在这里插入图片描述

  1. 第 1 行new 指令创建了一个 Man 对象,并将对象的内存地址压入栈中。
  2. 第 2 行dup 指令将栈顶的值复制一份并压入栈顶。因为接下来的 invokespecial 指令会消耗掉一个当前类的引用,所以需要复制一份。
  3. 第 3 行invokespecial 指令用于调用构造方法进行初始化。
  4. 第 4 行astore_1 指令将栈顶的 Man 对象引用弹出,并存入下标为 1 的局部变量 man 中。
  5. 第 5-8 行:与第 1-4 行类似,不同的是创建了 Woman 对象。
  6. 第 9 行aload_1 指令将局部变量 man 压入操作数栈中。
  7. 第 10 行invokevirtual 指令调用对象的成员方法 sayHello(),注意此时的对象类型为 com/itwanger/jvm/DynamicLinking$Human
  8. 第 11 行aload_2 指令将局部变量 woman 压入操作数栈中。
  9. 第 12 行:与第 10 行相同,调用 sayHello() 方法。

4.4 动态链接的解析过程

从字节码的角度来看,man.sayHello()woman.sayHello() 的字节码指令是完全相同的,但它们最终执行的目标方法却不同。这是因为 invokevirtual 指令在运行时的解析过程如下:

  1. 找到操作数栈顶的元素所指向的对象的实际类型,记作 C
  2. 在类型 C 中查找与常量池中的描述符匹配的方法
    • 如果找到匹配的方法,则进行访问权限校验。如果通过,则返回该方法的直接引用,查找结束。
    • 如果未通过校验,则抛出 java.lang.IllegalAccessError 异常。
  3. 如果未找到匹配的方法,则按照继承关系从下往上依次对 C 的各个父类进行第二步的搜索和验证
  4. 如果始终没有找到合适的方法,则抛出 java.lang.AbstractMethodError 异常

4.5 动态链接的本质

invokevirtual 指令在第一步就确定了运行时的实际类型,因此它并不是简单地将常量池中的符号引用解析为直接引用就结束了。它会根据方法接收者的实际类型来选择方法版本,这个过程就是 Java 重写的本质。我们把这种在运行期根据实际类型确定方法执行版本的过程称为动态链接。

5 方法返回地址

在 JVM 中,方法的退出有两种方式:正常退出异常退出。无论哪种方式,方法退出后都需要返回到方法最初被调用时的位置,以便程序能够继续执行。方法返回地址是栈帧中的一个重要组成部分,用于记录方法退出后控制流应返回的位置。

5.1 正常退出

当方法正常退出时,可能会有返回值传递给上层的方法调用者。方法是否有返回值以及返回值的类型由方法返回的指令决定。常见的返回指令包括:

  • ireturn:用于返回 int 类型。
  • lreturn:用于返回 long 类型。
  • freturn:用于返回 float 类型。
  • dreturn:用于返回 double 类型。
  • areturn:用于返回引用类型。
  • return:用于 void 方法的返回。

在方法正常退出时,PC(Program Counter)计数器的值会作为返回地址,栈帧中通常会保存这个计数器的值。返回地址记录了方法调用后下一条指令的位置,以便程序能够继续执行。

5.2 异常退出

当方法在执行过程中遇到异常且未被妥善处理时,方法会异常退出。在这种情况下,方法不会给上层调用者返回任何值。异常退出时,PC 计数器的值不会作为返回地址保存,因为异常处理机制会接管控制流,跳转到异常处理代码。

5.3 方法退出的过程

方法退出的过程实际上等同于将当前栈帧从栈中弹出(出栈)。出栈后,JVM 会执行以下操作:

  • 恢复上层方法的局部变量表和操作数栈:当前方法的栈帧出栈后,上层方法的栈帧成为当前栈帧,JVM 会恢复上层方法的局部变量表和操作数栈。
  • 将返回值压入调用者栈帧的操作数栈中:如果当前方法有返回值,JVM 会将返回值压入调用者栈帧的操作数栈中。
  • 调整 PC 计数器的值:PC 计数器的值会被更新为方法调用后的下一条指令的地址,以便程序能够继续执行。

5.4 PC 计数器

PC 计数器是 JVM 运行时数据区的一部分,用于跟踪当前线程执行字节码的位置。每个线程都有自己的 PC 计数器,记录当前执行的字节码指令的地址。

5.5 方法退出的示例

考虑以下代码片段:

public class MethodReturnExample {public static void main(String[] args) {int result = add(1, 2);System.out.println(result);}public static int add(int a, int b) {return a + b;}
}

main 方法中,调用了 add(1, 2) 方法。add 方法的返回值为 3,并通过 ireturn 指令返回给 main 方法。main 方法接收到返回值后,将其存储在局部变量 result 中,并打印输出。

5.6 异常退出的示例

考虑以下代码片段:

public class ExceptionExample {public static void main(String[] args) {try {throwException();} catch (Exception e) {System.out.println("Exception caught: " + e.getMessage());}}public static void throwException() throws Exception {throw new Exception("Test exception");}
}

throwException 方法中,抛出了一个异常。由于 main 方法中捕获了该异常,throwException 方法会异常退出。异常退出时,throwException 方法不会返回任何值给 main 方法,而是由异常处理机制接管控制流,跳转到 catch 块中执行。

6 附加信息

虚拟机规范允许具体的虚拟机实现增加一些额外的信息到栈帧中,例如与调试相关的信息。这些信息完全取决于具体的虚拟机实现。

7 StackOverflowError

StackOverflowError 是 Java 中常见的运行时异常,通常发生在递归调用过深或方法调用链过长,导致栈内存溢出时。下面通过两个示例代码来分析 StackOverflowError 的产生原因及堆栈信息。

7.1 示例代码 1:无限制递归调用

public class StackOverflowErrorTest {public static void main(String[] args) {StackOverflowErrorTest test = new StackOverflowErrorTest();test.testStackOverflowError();}public void testStackOverflowError() {testStackOverflowError();}
}

运行结果

运行上述代码时,会抛出 StackOverflowError 异常。

异常原因

testStackOverflowError() 方法是一个递归方法,它在方法体内直接调用了自身,且没有终止条件。每次调用 testStackOverflowError() 方法时,JVM 都会为该方法创建一个新的栈帧,并将其压入当前线程的栈中。由于递归调用没有终止条件,栈帧会不断累积,最终导致栈内存溢出,抛出 StackOverflowError 异常。

堆栈信息

异常堆栈信息如下:

Exception in thread "main" java.lang.StackOverflowErrorat com.yunyang.javabetter.jvm.stackframe.StackOverflowErrorTest.testStackOverflowError(StackOverflowErrorTest.java:17)at com.yunyang.javabetter.jvm.stackframe.StackOverflowErrorTest.testStackOverflowError(StackOverflowErrorTest.java:17)at com.yunyang.javabetter.jvm.stackframe.StackOverflowErrorTest.testStackOverflowError(StackOverflowErrorTest.java:17)at com.yunyang.javabetter.jvm.stackframe.StackOverflowErrorTest.testStackOverflowError(StackOverflowErrorTest.java:17)at com.yunyang.javabetter.jvm.stackframe.StackOverflowErrorTest.testStackOverflowError(StackOverflowErrorTest.java:17)...

从堆栈信息中可以看到,testStackOverflowError() 方法被重复调用,且每次调用的位置都在第 17 行(即方法体内的递归调用)。

7.2 示例代码 2:带计数的递归调用

为了更好地观察递归调用的次数,我们对代码进行了简单改造:

public class StackOverflowErrorTest1 {private static AtomicInteger count = new AtomicInteger(0);public static void main(String[] args) {while (true) {testStackOverflowError();}}public static void testStackOverflowError() {System.out.println(count.incrementAndGet());testStackOverflowError();}
}

运行结果

在运行上述代码时,程序会不断递归调用 testStackOverflowError() 方法,并打印递归调用的次数。当递归调用达到一定次数时,栈内存溢出,抛出 StackOverflowError 异常。

在我的本地环境中,递归调用次数达到 11457 次时,抛出了 StackOverflowError 异常。

异常原因

与示例代码 1 类似,testStackOverflowError() 方法是一个递归方法,它在方法体内直接调用了自身,且没有终止条件。每次调用时,JVM 都会为该方法创建一个新的栈帧,并将其压入当前线程的栈中。由于递归调用没有终止条件,栈帧会不断累积,最终导致栈内存溢出,抛出 StackOverflowError 异常。

堆栈信息

异常堆栈信息如下:

11456
11457
Exception in thread "main" java.lang.StackOverflowErrorat sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271)...

从堆栈信息中可以看到,递归调用次数达到 11457 次时,栈内存溢出,抛出 StackOverflowError 异常。

8 总结

栈帧是 JVM 中用于方法执行的核心数据结构,每个方法调用都会创建一个栈帧,并在方法执行完毕后销毁。栈帧的局部变量表和操作数栈的大小在编译时确定,动态链接支持方法调用中的多态性,方法返回地址记录了方法结束后的控制流位置。理解栈帧对于深入理解 Java 程序的运行机制至关重要。

9 思维导图

在这里插入图片描述

10 参考链接

深入理解 JVM 的栈帧结构

相关文章:

JVM 栈帧结构详解

在 Java 虚拟机(JVM)中,栈帧(Stack Frame)是用于支持方法调用和方法执行的关键数据结构。每个方法从调用开始到执行完成,都对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。本文将详细介绍 JVM 栈帧的结构及…...

HTML和JavaScript实现商品购物系统

下面是一个更全面的商品购物系统示例,包含新增商品、商品的增加删除以及结算找零的功能。这个系统使用HTML和JavaScript实现。 1.功能说明: 这个应用程序使用纯HTML和JavaScript实现。 包含一个商品列表和一个购物车区域。商品列表中有几个示例商品&a…...

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验三----学校选址与路径规划(超超超详细!!!)

目录 实验三 学校选址与道路规划 3.1 实验内容及目的 3.1.1 实验内容 3.1.2 实验目的 3.2 实验方案 3.3 操作流程 3.3.1 环境设置 3.3.2 地势分析 (1)提取坡度: (2)重分类: 3.3.3 学校点分析 (1)欧氏距离: (2)重分类: 3.3.4 娱乐场所点分析 (1)欧氏距离…...

ip_done

文章目录 路由结论 IP分片 数据链路层重谈Mac地址MAC帧报头局域网的通信原理MSS,以及MAC帧对上层的影响ARP协议 1.公司是不是这样呢? 类似的要给运营商交钱,构建公司的子网,具有公司级别的入口路由器 2.为什么要这样呢?? IP地…...

Mysql体系架构剖析——岁月云实战笔记

1 体系架构 理论内容阅读了mysql体系架构剖析,其他的根据岁月云的实战进行记录。 1.1 连接层 mysql最上层为连接服务,引入线程池,允许多台客户端连接,主要工作:连接处理、授权认证、安全防护、管理连接等。 连接处理&a…...

【卷积神经网络】AlexNet实践

构建模型 模版搭建 # 定义一个AlexNet模型类def __init__(self):# 调用父类的构造函数(如果继承自nn.Module的话)super(AlexNet, self).__init__()# ReLU激活函数self.ReLU nn.ReLU()# 卷积层1:输入1个通道(灰度图)&a…...

LF CRLF

这个提示的含义是:Git 检测到你当前的 file3.txt 文件中使用了 LF(换行符,Line Feed,\n) 作为换行符,但在你系统的 Git 配置中,指定要将其转换为 CRLF(回车换行,Carriage…...

Python学习(二)—— 基础语法(上)

目录 一,表达式和常量和变量 1.1 表达式 1.2 变量 1.3 动态类型特性 1.4 输入 二,运算符 2.1 算术运算符 2.2 关系运算符 2.3 逻辑运算符 2.4 赋值运算符 2.5 练习 三,语句 3.1 条件语句 3.2 while循环 3.3 for循环 四&#…...

科研绘图系列:R语言绘制网络图和密度分布图(network density plot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载图1图2图3图4图5图6图7图8系统信息参考介绍 R语言绘制网络图和密度分布图(network & density plot) 加载R包 library(magrittr) library(dplyr) library(…...

python解题之寻找最大的葫芦

问题描述 问题描述 在一场经典的德州扑克游戏中,有一种牌型叫做“葫芦”。“葫芦”由五张牌组成,其中包括三张相同牌面值的牌 �a 和另外两张相同牌面值的牌 �b。如果两个人同时拥有“葫芦”,我们会优先比较牌 &#…...

openwrt安装tailscale

1. 下载 进入tailscale的github仓库复制最新版本的链接:点击跳转 wget https://github.com/adyanth/openwrt-tailscale-enabler/releases/download/v1.36.1-fb2f6cf-autoupdate/openwrt-tailscale-enabler-v1.36.1-fb2f6cf-autoupdate.tgz2.解压缩 tar x -zvC / …...

基于物联网的智能插座云平台 WIFI云平台MQTT协议

功能介绍 功能描述: STM32单片机为控制核心 LCD1602液晶显示当前时间温度 开启时间 关闭时间 按键设置开启时间/关闭时间,温度报警上限 到开启时间,继电器自动打开,到关闭时间,自动关闭 通过DS18B20温度传感器获…...

MySQL 事务

概念介绍 事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组 DML 语句要么全部成功,要么全部失败,是一个整体。MySQL 提供一种机制,保证我们达到这样的效果。 事务就是要做的或所做的事情,主要用…...

消息中间件面试题-参考回答

消息中间件面试题-参考回答 面试官:RabbitMQ-如何保证消息不丢失 候选人: 嗯!我们当时MYSQL和Redis的数据双写一致性就是采用RabbitMQ实现同步的,这里面就要求了消息的高可用性,我们要保证消息的不丢失。主要从三个层面…...

解决 MyBatis 中空字符串与数字比较引发的条件判断错误

问题复现 假设你在 MyBatis 的 XML 配置中使用了如下代码&#xff1a; <if test"isCollect ! null"><choose><when test"isCollect 1">AND exists(select 1 from file_table imgfile2 where task.IMAGE_SEQimgfile2.IMAGE_SEQ and im…...

【ETCD】【源码阅读】深入解析 etcd 的 `EtcdServer.Start` 函数

深入解析 etcd 的 EtcdServer.Start 函数 在 etcd 的代码中&#xff0c;EtcdServer.Start 是一个关键方法&#xff0c;用于初始化并启动服务器以便处理请求。本文将从源码的角度逐步分析此函数的每一步操作。 函数签名及注释 // Start performs any initialization of the Se…...

嵌入式驱动开发详解16(音频驱动开发)

文章目录 前言WM8960简介I2S协议接口说明 SAI音频接口简介驱动框架简介设备树配置内核使能声卡设置与测试 后续参考文献 前言 该专栏主要是讲解嵌入式相关的驱动开发&#xff0c;但是由于ALSA驱动框架过于复杂&#xff0c;实现音频编解码芯片的驱动不是一个人能完成的&#xf…...

【数据结构——查找】二分查找(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;实现二分查找的算法。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.根据键盘输入的一组有序数据建立顺序表&#xff0c;2.顺序表的输…...

探索云原生数据库 PolarDB

引言 在云计算时代,数据库的重要性不言而喻。随着企业数字化转型的加速,对数据库的性能、可靠性和灵活性的要求也越来越高。阿里云推出的云原生数据库 PolarDB,正是为了满足这些需求而设计的一款高性能、兼容性强、弹性灵活的关系型数据库产品。本文将详细介绍 PolarDB 的特…...

OGG FOR MYSQL同步DDL

以下实验测试OGG FOR mysql 同步DDL&#xff0c; OGG 21.3 MYSQL 8.0.27 --创建测试数据 create table oggddl_20241201 (oid int primary key ,oname varchar(10)); create table oggddl_20241202 (oid int primary key ,oname varchar(10)); create table oggddl_20241203…...

【CAN】asc报文格式文件合并(python版)

目录 一、简介二、合并asc格式报文1、准备多个asc文件2、根据时间合并asc文件3、结果 三、总结四、参考 一、简介 CAN通信&#xff1a;CAN&#xff08;Controller Area Network&#xff09;是一种多主方式的串行通讯总线。基本设计规范要求有高位速率、高抗电磁干扰性&#xf…...

C++之STL的map容器

map map的实现方式 set是一个有序的关联容器&#xff0c;是基于平衡二叉搜索树(红黑树)实现的&#xff0c;元素是有序的 map的用法 #include <iostream> #include <map> using namespace std;const int ADDSIZE 20; int main() {map<int, int> m;cout &…...

基于卷积神经网络的图像二分类检测模型训练与推理实现教程 | 幽络源

前言 对于本教程&#xff0c;说白了&#xff0c;就是期望能通过一个程序判断一张图片是否为某个物体&#xff0c;或者说判断一张图片是否为某个缺陷。因为本教程是针对二分类问题&#xff0c;因此主要处理 是 与 不是 的问题&#xff0c;比如我的模型是判断一张图片是否为苹果…...

react-dnd 拖拽事件与输入框的文本选中冲突

问题描述 当我们使用拖拽库的时候&#xff0c;往往会遇到拖拽的一个元素他的子孙元素有输入框类型的dom节点&#xff0c;当拖拽的事件绑定在该元素身上时候&#xff0c;发现子孙的输入框不能进行文本选中了&#xff0c;会按住鼠标去选中文本的时候会触发拖拽 实际的效果&…...

‘Close Project‘ is not available while IDEA is updating indexes的解决

XXX is not available while IDEA is updating indexes IDEA 1.Remove from Recent Projects 2.重新 Open工程即可...

如何解决samba服务器共享文件夹不能粘贴文件

sudo vim /etc/samba/smb.conf在samba的配置文件中增加一个选项 writable yes重启Samba服务以使更改生效&#xff1a; sudo service smbd restart...

Three.js入门-材质详解,构建视觉真实感的核心

Three.js 材质详解&#xff1a;构建视觉真实感的核心 Three.js 是一个强大的 3D JavaScript 库&#xff0c;它为开发者提供了丰富的工具来创建和渲染逼真的三维场景。在这些工具中&#xff0c;材质是一个非常重要的组成部分。材质定义了物体表面的外观特性&#xff0c;例如颜色…...

GitHub、Google等镜像加速地址收集

GitHub、Google等镜像加速地址收集 摘要 本文用于收集GitHub、Google等镜像/加速地址。 GitHub GitHub加速地址一览 fastgithub Https://www.fastgithub.com/&#xff08;推荐&#xff09; 站源地址缓存github.comwww.fastgithub.com无raw.githubusercontent.com无github.gi…...

五、网络层:控制平面,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》

目录 一、导论 二、路由选择算法 2.1 路由&#xff08;route&#xff09;的概念 2.2 网络的图抽象 2.2.1 边和路由的代价 2.2.2 最优化原则 2.3 路由的原则 2.4 路由选择算法的分类 2.5 link state 算法 2.5.1 LS路由工作过程 2.5.2 链路状态路由选择&#xff08;lin…...

Fix the “The repository no longer has a Release file” error on Ubuntu 23.04

背景信息 在Ubuntu 23.04操作系统上执行apt-get update命令更新操作系统时&#xff0c;得到以下错误 登录后复制 # apt-get update Ign:1 http://mirrors.aliyun.com/ubuntu lunar InRelease Ign:2 http://mirrors.aliyun.com/ubuntu lunar-updates InRelease Ign:3 http://mir…...

开源 AI 智能名片 S2B2C 商城小程序对私域流量运营的全方位助力

在当今竞争激烈的商业环境中&#xff0c;私域流量运营已成为企业实现可持续发展和提升竞争力的关键策略之一。开源 AI 智能名片 S2B2C 商城小程序凭借其独特的功能与特性&#xff0c;从多个维度为私域流量运营提供了强有力的支持与推动&#xff0c;以下将详细阐述其在各个方面的…...

Java Exception解决方法

Java中的Exception是所有异常的基类&#xff0c;它指的是程序在执行过程中发生的非严重错误&#xff0c;比如空指针异常、数组越界异常等。 为了解决Java中的Exception&#xff0c;从以下步骤进行排查解决&#xff1a; 阅读错误信息&#xff1a;查看异常的完整堆栈跟踪信息&a…...

HCIA-Access V2.5_2_2_2网络通信基础_IP编址与路由

网络层数据封装 首先IP地址封装在网络层&#xff0c;它用于标识一台网络设备&#xff0c;其中IP地址分为两个部分&#xff0c;网络地址和主机地址&#xff0c;通过我们采用点分十进制的形式进行表示。 IP地址分类 对IP地址而言&#xff0c;它细分为五类&#xff0c;A,B,C,D,E,…...

JeecgBoot passwordChange 任意用户密码重置漏洞复现

0x01 产品简介 Jeecg Boot是一个企业级低代码开发平台,基于前后端分离的架构,融合了SpringBoot、SpringCloud、Ant Design、Vue、Mybatis-plus、Shiro、JWT等多种主流技术,旨在帮助企业快速构建各种应用系统,提高开发效率,降低开发成本。采用最新主流的前后分离框架,使得…...

7-8 整型关键字的散列映射

给定一系列整型关键字和素数 p&#xff0c;用除留余数法定义的散列函数 H(key)key%p 将关键字映射到长度为 p 的散列表中。用线性探测法解决冲突。 输入格式: 输入第一行首先给出两个正整数 n&#xff08;≤1000&#xff09;和 p&#xff08;≥n 的最小素数&#xff09;&…...

谷粒商城—分布式高级①.md

1. ELASTICSEARCH 1、安装elastic search dokcer中安装elastic search (1)下载ealastic search和kibana docker pull elasticsearch:7.6.2 docker pull kibana:7.6.2(2)配置 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data echo "h…...

MySQL SQL语句性能优化

MySQL SQL语句性能优化指南 一、查询设计优化1. 避免 SELECT *2. 使用 WHERE 进行条件过滤3. 避免在索引列上使用函数和表达式4. 使用 LIMIT 限制返回行数5. 避免使用子查询6. 优化 JOIN 操作7. 避免全表扫描 二、索引优化1. 使用合适的索引2. 覆盖索引3. 索引选择性4. 多列索引…...

【潜意识Java】期末考试可能考的选择题(附带答案解析)

目录 选择题一&#xff1a;Java 数据类型 选择题二&#xff1a;Java 控制结构 选择题三&#xff1a;面向对象编程 选择题四&#xff1a;Java 集合框架 选择题五&#xff1a;Java 异常处理 选择题六&#xff1a;Java 方法 选择题七&#xff1a;Java 流程控制 选择题八&a…...

修炼之道 --- 其一

序言 大家对面试中的面经八股文是怎样的看法呢&#xff0c;从他的名字 八股文 就可以看出来大家可能并不喜欢他&#xff0c;八股文一般是 死板、浮于表面、不重实际 的特点。但是&#xff0c;我们需要通过辩证的角度来看待一个事情&#xff0c;不能单方面来定性&#xff01;  …...

【前端】HTML

目录 一、HTML结构 1.1 HTML标签1.2 HTML文件基本结构1.3 快速生成框架 二、HTML常见标签 2.1 注释标签 !-- –2.2 标题标签 h1到h62.3 段落标签 p2.4 换行标签 br2.5 格式化标签2.6 图片标签 img2.7 超链接标签 a 三、表格标签 3.1 常用标签3.2 合并单元格 四、列表标签五、表…...

LabVIEW实现GPS通信

目录 1、GPS通信原理 2、硬件环境部署 3、程序架构 4、前面板设计 5、程序框图设计 6、测试验证 本专栏以LabVIEW为开发平台,讲解物联网通信组网原理与开发方法,覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合实际案例,展示如何利用LabVIEW和常用模块实现物联网系…...

【Python 小课堂】第 2 课 Python 基础知识:语句、常量、变量和注释

第 2 课 基础知识&#xff1a;语句、常量/变量和注释 By Yichen Li 2024/12/14 一、内容简介 在本次课中&#xff0c;介绍Python语句、常量/变量以及代码注释的基本概念&#xff0c;一些详细的概念、扩展及用法等细节&#xff0c;留至后续介绍。 二、Python语句 一般来说&…...

基于STM32设计的工地扬尘与噪音实时监测系统(网页)

一、前言 当前项目使用的相关软件工具、传感器源代码工程已经上传到网盘&#xff08;实时更新项目内容&#xff09;&#xff1a;https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?fromfrom_copylink 1.1 项目开发背景 近年来&#xff0c;随着城市化进程的…...

LLM之RAG实战(五十)| FastAPI:构建基于LLM的WEB接口界面

FastAPI是WEB UI接口&#xff0c;随着LLM的蓬勃发展&#xff0c;FastAPI的生态也迎来了新的机遇。本文将围绕FastAPI、OpenAI的API以及FastCRUD&#xff0c;来创建一个个性化的电子邮件写作助手&#xff0c;以展示如何结合这些技术来构建强大的应用程序。 下面我们开始分步骤操…...

JavaScript 中的 Map方法

JavaScript 中的 Map方法 在 JavaScript 中&#xff0c;Map 是一种用于存储键值对的数据结构&#xff0c;相较于传统的对象&#xff08;Object&#xff09;&#xff0c;Map 提供了更高效的键值对操作方式适合处理需要频繁操作键值对的场景。 1. 创建 Map const map new Map…...

img引入svg如何修改颜色

方法1&#xff1a;通过css中filter:drop-shadow 首先需要一个容纳图标的父盒子(下方实例中的.svg-img)&#xff0c;通过css造一个图标的‘影子’&#xff08;.svg-color中的drop-shadow&#xff09;&#xff0c;然后设置‘影子’的颜色&#xff0c;再把图标本体移出父盒子&…...

自然语言处理基础及应用场景

自然语言处理定义 让计算机理解人所说的文本 语音 Imitation Game 图灵测试 行为主义 鸭子理论 自然语言处理的基本任务 词性标注&#xff1a;区分每个词名词、动词、形容词等词性命名实体的识别&#xff1a;名词的具体指代是哪一类事物共指消解&#xff1a;代词指代的是前面…...

构建centos docker基础镜像

1、介绍 比较老的版本docker镜像&#xff0c;不太好找&#xff0c;可以尝试自己构建 各版本构建基础镜像方法不太一样&#xff0c;方式也不同&#xff0c;自己尝试&#xff0c;本文只介绍了我自己的尝试 2、构建centos5.11 docker镜像 准备iso文件 &#xff08;1&#xff09;安…...

etcd命令大全

默认安装自带etcdctl 命令行客户端&#xff0c;分两个版本ETCDCTL_API2和ETCDCTL_API3&#xff0c;两个版本不一样&#xff0c;操作的数据也不相容。 本文以v3 为例。 使用之前需要先设置&#xff1a;export ETCDCTL_API3。 1 etcd查询集群节点列表及状态 标准输出&#xff1…...

Go有限状态机实现和实战

Go有限状态机实现和实战 有限状态机 什么是状态机 有限状态机&#xff08;Finite State Machine, FSM&#xff09;是一种用于建模系统行为的计算模型&#xff0c;它包含有限数量的状态&#xff0c;并通过事件或条件实现状态之间的转换。FSM的状态数量是有限的&#xff0c;因此称…...