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

JVM(三)——字节码技术

三、字节码技术

在这里插入图片描述

1、类文件结构

一个简单的 HelloWorld.java

package com.mysite.jvm.t5;
// HelloWorld 示例
public class HelloWorld {public static void main(String[] args) {System.out.println("hello world");}
}

执行 javac -parameters -d . HellowWorld.java
编译为 HelloWorld.class 后是这个样子的:

[root@localhost ~]# od -t xC HelloWorld.class
0000000 ca fe ba be 00 00 00 34 00 23 0a 00 06 00 15 09
0000020 00 16 00 17 08 00 18 0a 00 19 00 1a 07 00 1b 07
0000040 00 1c 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29
0000060 56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e
0000100 75 6d 62 65 72 54 61 62 6c 65 01 00 12 4c 6f 63
0000120 61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 01
0000140 00 04 74 68 69 73 01 00 1d 4c 63 6e 2f 69 74 63
0000160 61 73 74 2f 6a 76 6d 2f 74 35 2f 48 65 6c 6c 6f
0000200 57 6f 72 6c 64 3b 01 00 04 6d 61 69 6e 01 00 16
0000220 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72
0000240 69 6e 67 3b 29 56 01 00 04 61 72 67 73 01 00 13
0000260 5b 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69
0000300 6e 67 3b 01 00 10 4d 65 74 68 6f 64 50 61 72 61
0000320 6d 65 74 65 72 73 01 00 0a 53 6f 75 72 63 65 46
0000340 69 6c 65 01 00 0f 48 65 6c 6c 6f 57 6f 72 6c 64
0000360 2e 6a 61 76 61 0c 00 07 00 08 07 00 1d 0c 00 1e
0000400 00 1f 01 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64
0000420 07 00 20 0c 00 21 00 22 01 00 1b 63 6e 2f 69 74
0000440 63 61 73 74 2f 6a 76 6d 2f 74 35 2f 48 65 6c 6c
0000460 6f 57 6f 72 6c 64 01 00 10 6a 61 76 61 2f 6c 61
0000500 6e 67 2f 4f 62 6a 65 63 74 01 00 10 6a 61 76 61
0000520 2f 6c 61 6e 67 2f 53 79 73 74 65 6d 01 00 03 6f
0000540 75 74 01 00 15 4c 6a 61 76 61 2f 69 6f 2f 50 72
0000560 69 6e 74 53 74 72 65 61 6d 3b 01 00 13 6a 61 76
0000600 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d
0000620 01 00 07 70 72 69 6e 74 6c 6e 01 00 15 28 4c 6a
0000640 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b
0000660 29 56 00 21 00 05 00 06 00 00 00 00 00 02 00 01
0000700 00 07 00 08 00 01 00 09 00 00 00 2f 00 01 00 01
0000720 00 00 00 05 2a b7 00 01 b1 00 00 00 02 00 0a 00
0000740 00 00 06 00 01 00 00 00 04 00 0b 00 00 00 0c 00
0000760 01 00 00 00 05 00 0c 00 0d 00 00 00 09 00 0e 00
0001000 0f 00 02 00 09 00 00 00 37 00 02 00 01 00 00 00
0001020 09 b2 00 02 12 03 b6 00 04 b1 00 00 00 02 00 0a
0001040 00 00 00 0a 00 02 00 00 00 06 00 08 00 07 00 0b
0001060 00 00 00 0c 00 01 00 00 00 09 00 10 00 11 00 00
0001100 00 12 00 00 00 05 01 00 10 00 00 00 01 00 13 00
0001120 00 00 02 00 14

根据 JVM 规范,类文件结构如下

ClassFile {u4 magic;			// 魔数     4 byteu2 minor_version;	// 最小版本号  2 byteu2 major_version;	// 最大版本号  2 byteu2 constant_pool_count;// 常量池数量cp_info constant_pool[constant_pool_count-1];	// 常量池内容u2 access_flags;	// 访问修饰符u2 this_class;		// 自己的类名信息u2 super_class;		// 父类信息u2 interfaces_count;// 接口数量u2 interfaces[interfaces_count];	//接口u2 fields_count;	// 成员变量数量field_info fields[fields_count];	// 成员变量内容u2 methods_count;	// 方法数量method_info methods[methods_count];	// 方法内容u2 attributes_count;	// 其他的属性信息attribute_info attributes[attributes_count];	
}

1)魔数

0~3 字节,表示它是否是【class】类型的文件

0000000 ca fe ba be 00 00 00 34 00 23 0a 00 06 00 15 09

2)版本

4~7字节,表示类的版本 00 34(52)表示 Java 8

0000000 ca fe ba be 00 00 00 34 00 23 0a 00 06 00 15 09

3)常量池

在这里插入图片描述

详细见《深入理解深入理解Java虚拟机:JVM高级特性与最佳实践(第3版) (周志明) 》- p303

详细见Java虚拟机规范参考文档

2、字节码指令

1)入门

2)javap 工具

通过 javap 工具反编译 class 文件

javap -v ./Demo.class

3)图解方法执行流程

3.1 原始 java 代码
package cn.itcast.jvm.t3.bytecode;
/**
* 演示 字节码指令 和 操作数栈、常量池的关系
*/
public class Demo3_1 {public static void main(String[] args) {int a = 10;int b = Short.MAX_VALUE + 1;int c = a + b;System.out.println(c);}
}
3.2 编译后的字节码文件
[root@localhost ~]# javap -v Demo3_1.class
Classfile /root/Demo3_1.class
Last modified Jul 7, 2019; size 665 bytes
MD5 checksum a2c29a22421e218d4924d31e6990cfc5
Compiled from "Demo3_1.java"
public class cn.itcast.jvm.t3.bytecode.Demo3_1
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#26 // java/lang/Object."<init>":()V
#2 = Class #27 // java/lang/Short
#3 = Integer 32768
#4 = Fieldref #28.#29 //
java/lang/System.out:Ljava/io/PrintStream;
#5 = Methodref #30.#31 // java/io/PrintStream.println:(I)V
#6 = Class #32 // cn/itcast/jvm/t3/bytecode/Demo3_1
#7 = Class #33 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 LocalVariableTable
#13 = Utf8 this
#14 = Utf8 Lcn/itcast/jvm/t3/bytecode/Demo3_1;
#15 = Utf8 main
#16 = Utf8 ([Ljava/lang/String;)V
#17 = Utf8 args
#18 = Utf8 [Ljava/lang/String;
#19 = Utf8 a
#20 = Utf8 I
#21 = Utf8 b
#22 = Utf8 c
#23 = Utf8 MethodParameters
#24 = Utf8 SourceFile
#25 = Utf8 Demo3_1.java
#26 = NameAndType #8:#9 // "<init>":()V
#27 = Utf8 java/lang/Short
#28 = Class #34 // java/lang/System
#29 = NameAndType #35:#36 // out:Ljava/io/PrintStream;
#30 = Class #37 // java/io/PrintStream
#31 = NameAndType #38:#39 // println:(I)V
#32 = Utf8 cn/itcast/jvm/t3/bytecode/Demo3_1
#33 = Utf8 java/lang/Object
#34 = Utf8 java/lang/System
#35 = Utf8 out
#36 = Utf8 Ljava/io/PrintStream;
#37 = Utf8 java/io/PrintStream
#38 = Utf8 println
#39 = Utf8 (I)V
{
public cn.itcast.jvm.t3.bytecode.Demo3_1();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."
<init>":()V4: returnLineNumberTable:line 6: 0LocalVariableTable:Start Length Slot Name Signature0 		5 	  0   this Lcn/itcast/jvm/t3/bytecode/Demo3_1;
public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=4, args_size=10: bipush 102: istore_13: ldc #3 				// int 327685: istore_26: iload_17: iload_28: iadd9: istore_310: getstatic #4 		// Field
java/lang/System.out:Ljava/io/PrintStream;13: iload_314: invokevirtual #5 	// Method
java/io/PrintStream.println:(I)V17: returnLineNumberTable:line 8: 0line 9: 3line 10: 6line 11: 10line 12: 17LocalVariableTable:Start Length Slot Name Signature0  		18 	   0  args [Ljava/lang/String;3  		15 	   1  a		 I6  		12 	   2  b		 I10  	8 	   3  c 	 I
MethodParameters:
Name Flags
args
}
3.3 常量池载入运行时常量池

超出了整数的范围的存储在运行时常量池中,未超出和字节码指令放在一起。
在这里插入图片描述

3.4 方法字节码载入方法区

在这里插入图片描述

3.5main 线程开始运行,分配栈帧内存

(stack = 2, locals = 4)
在这里插入图片描述

3.6执行引擎开始执行字节码

bipush 10

  • 将一个 byte 压入操作数栈(其长度会补齐 4 个字节),类似的指令还有
  • sipush 将一个 short 压入操作数栈(其长度会补齐 4 个字节)
  • ldc 将一个 int 压入操作数栈
  • ldc2_w 将一个 long 压入操作数栈(分两次压入,因为 long 是 8 个字节)
  • 这里小的数字都是和字节码指令存在一起,超过 short 范围的数字存入了常量池
    在这里插入图片描述

istore_1

  • 将操作数栈顶数据弹出,存入局部变量表的 slot 1
    在这里插入图片描述在这里插入图片描述

ldc #3

  • 从常量池加载 #3 数据到操作数栈
  • 注意 Short.MAX_VALUE 是 32767,所以 32768 = Short.MAX_VALUE + 1 实际是在编译期间计算好的
    在这里插入图片描述

istore_2在这里插入图片描述在这里插入图片描述

iload_1
在这里插入图片描述

iload_2
在这里插入图片描述

iadd在这里插入图片描述
在这里插入图片描述

getstatic #4
在这里插入图片描述
在这里插入图片描述

iload_3
在这里插入图片描述
在这里插入图片描述

invokevirtual #5

  • 找到常量池 #5 项
  • 定位到方法区 java/io/PrintStream.println:(I)V 方法
  • 生成新的栈帧(分配 locals、stack等)
  • 传递参数,执行新栈帧中的字节码

在这里插入图片描述

  • 执行完毕,弹出栈帧
  • 清除 main 操作数栈内容

在这里插入图片描述
return

  • 完成 main 方法调用,弹出 main 栈帧
  • 程序结束

4)构造方法

4.1 <cinit>()V
public class Demo3_8_1 {static int i = 10;static {i = 20;}static {i = 30;}
}

编译器会按从上至下的顺序,收集所有 static 静态代码块和静态成员赋值的代码,合并为一个特殊的方法 <cinit>()V :

0: bipush 10
2: putstatic #2 // Field i:I
5: bipush 20
7: putstatic #2 // Field i:I
10: bipush 30
12: putstatic #2 // Field i:I
15: return

<cinit>()V 方法会在类加载的初始化阶段被调用

2)<init>()V
public class Demo3_8_2 {private String a = "s1";{b = 20;}private int b = 10;{a = "s2";}public Demo3_8_2(String a, int b) {this.a = a;this.b = b;}public static void main(String[] args) {Demo3_8_2 d = new Demo3_8_2("s3", 30);System.out.println(d.a);System.out.println(d.b);}
}

编译器会按从上至下的顺序,收集所有 {} 代码块和成员变量赋值的代码,形成新的构造方法,但原始构
造方法内的代码总是在最后

public cn.itcast.jvm.t3.bytecode.Demo3_8_2(java.lang.String, int);
descriptor: (Ljava/lang/String;I)V
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: aload_0
1: invokespecial #1 // super.<init>()V
4: aload_0
5: ldc #2 // <- "s1"
7: putfield #3 // -> this.a
10: aload_0
11: bipush 20 // <- 20
13: putfield #4 // -> this.b
16: aload_0
17: bipush 10 // <- 10
19: putfield #4 // -> this.b
22: aload_0
23: ldc #5 // <- "s2"
25: putfield #3 // -> this.a
28: aload_0 // ------------------------------
29: aload_1 // <- slot 1(a) "s3" |
30: putfield #3 // -> this.a |
33: aload_0 |
34: iload_2 // <- slot 2(b) 30 |
35: putfield #4 // -> this.b --------------------
38: return
LineNumberTable: ...
LocalVariableTable:
Start Length Slot Name Signature
0 39 0 this Lcn/itcast/jvm/t3/bytecode/Demo3_8_2;
0 39 1 a Ljava/lang/String;
0 39 2 b I
MethodParameters: ...

5)方法调用

public class Demo3_9 {public Demo3_9() { }private void test1() { }private final void test2() { }public void test3() { }public static void test4() { }public static void main(String[] args) {Demo3_9 d = new Demo3_9();d.test1();d.test2();d.test3();d.test4();Demo3_9.test4();}
}

字节码:

0: new #2 			// class cn/itcast/jvm/t3/bytecode/Demo3_9
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokespecial #4 // Method test1:()V
12: aload_1
13: invokespecial #5 // Method test2:()V
16: aload_1
17: invokevirtual #6 // Method test3:()V
20: aload_1
21: pop
22: invokestatic #7 // Method test4:()V
25: invokestatic #7 // Method test4:()V
28: return
  • new 是创建【对象】,给对象分配堆内存,执行成功会将【对象引用】压入操作数栈
  • dup 是赋值操作数栈栈顶的内容,本例即为【对象引用】,为什么需要两份引用呢,一个是要配合 invokespecial 调用该对象的构造方法 “<init>”: ()V (会消耗掉栈顶一个引用),另一个要配合 astore_1 赋值给局部变量
  • 最终方法(final),私有方法(private),构造方法都是由 invokespecial 指令来调用,属于静态绑定
  • 普通成员方法是由 invokevirtual 调用,属于动态绑定,即支持多态
  • 成员方法与静态方法调用的另一个区别是,执行方法前是否需要【对象引用】
  • 比较有意思的是 d.test4(); 是通过【对象引用】调用一个静态方法,可以看到在调用
  • invokestatic 之前执行了 pop 指令,把【对象引用】从操作数栈弹掉了😂
    还有一个执行 invokespecial 的情况是通过 super 调用父类方法

6)多态的原理

当执行 invokevirtual 指令时,

  1. 先通过栈帧中的对象引用找到对象
  2. 分析对象头,找到对象的实际 Class
  3. Class 结构中有 vtable,它在类加载的链接阶段就已经根据方法的重写规则生成好了
  4. 查表得到方法的具体地址
  5. 执行方法的字节码

所以说多态中调用方法性能不如 invokespecial 和 invokestatic 指令 即私有方法、和带有 final 和 static 关键字的方法。

7)异常处理

try-catch

public class Demo3_11_1 {public static void main(String[] args) {int i = 0;try {i = 10;} catch (Exception e) {i = 20;}}
}
public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=3, args_size=10: iconst_01: istore_12: bipush 	104: istore_15: goto 	128: astore_29: bipush 	2011: istore_112: returnException table:from to target type2 5 8 Class java/lang/ExceptionLineNumberTable: ...LocalVariableTable:Start Length Slot Name Signature9 3 2 e Ljava/lang/Exception;0 13 0 args [Ljava/lang/String;2 11 1 i IStackMapTable: ...MethodParameters: ...
}
  • 可以看到多出来一个 Exception table 的结构,[from, to) 是前闭后开的检测范围,一旦这个范围内的字节码执行出现异常,则通过 type 匹配异常类型,如果一致,进入 target 所指示行号
  • 8 行的字节码指令 astore_2 是将异常对象引用存入局部变量表的 slot 2 位置

finally

public class Demo3_11_4 {public static void main(String[] args) {int i = 0;try {i = 10;} catch (Exception e) {i = 20;} finally {i = 30;}}
}
public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=4, args_size=10: iconst_01: istore_1			// 0 -> i2: bipush 		10	// try --------------------------------------4: istore_1 		// 10 -> i |5: bipush 		30 	// finally |7: istore_1 		// 30 -> i |8: goto 		27 	// return -----------------------------------11: astore_2 		// catch Exceptin -> e ----------------------12: bipush 		20 	// |14: istore_1 		// 20 -> i |15: bipush 		30 	// finally |17: istore_1 		// 30 -> i |18: goto 		27 	// return -----------------------------------21: astore_3 		// catch any -> slot 3 ----------------------22: bipush 		30 	// finally |24: istore_1 		// 30 -> i |25: aload_3 		// <- slot 3 |26: athrow 			// throw ------------------------------------27: returnException table:from to target type2   5   11 	Class java/lang/Exception2   5   21    any // 剩余的异常类型,比如 Error11  15  21    any // 剩余的异常类型,比如 ErrorLineNumberTable: ...LocalVariableTable:Start Length Slot Name Signature12 3 2 e Ljava/lang/Exception;0 28 0 args [Ljava/lang/String;2 26 1 i IStackMapTable: ...MethodParameters: ...

可以看到 finally 中的代码被复制了 3 份,分别放入 try 流程,catch 流程以及 catch 剩余的异常类型流
程。
注意:如果在 finally 块中,直接 return 会吞掉异常 (字节码athrow 指令)。

8)synchronized

public class Demo3_13 {public static void main(String[] args) {Object lock = new Object();synchronized (lock) {System.out.println("ok");}}
}
Code:stack=2, locals=4, args_size=10: new           #2                  // class java/lang/Object3: dup // 复制一份栈顶,然后压入栈中。用于函数消耗4: invokespecial #1                  // Method java/lang/Object."<init>":()V7: astore_1 // 将栈顶的对象地址方法 局部变量表中 1 中8: aload_1 // 加载到操作数栈9: dup // 复制一份,放到操作数栈,用于加锁时消耗10: astore_2 // 将操作数栈顶元素弹出,暂存到局部变量表的 2 号槽位。这时操作数栈中有一份对象的引用11: monitorenter // 加锁12: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;15: ldc           #4                  // String ok17: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V20: aload_2 // 加载对象到栈顶21: monitorexit // 释放锁22: goto          30// 异常情况的解决方案 释放锁!25: astore_326: aload_227: monitorexit28: aload_329: athrow30: return// 异常表!Exception table:from    to  target type12    22    25   any25    28    25   anyLineNumberTable: ...LocalVariableTable:Start Length Slot Name Signature0 31 0 args [Ljava/lang/String;8 23 1 lock Ljava/lang/Object;

相关文章:

JVM(三)——字节码技术

三、字节码技术 1、类文件结构 一个简单的 HelloWorld.java package com.mysite.jvm.t5; // HelloWorld 示例 public class HelloWorld {public static void main(String[] args) {System.out.println("hello world");} }执行 javac -parameters -d . HellowWorld.…...

HarmonyOS 应用开发之Stage模型绑定FA模型ServiceAbility

本小节介绍Stage模型的两种应用组件如何绑定FA模型ServiceAbility组件。 UIAbility关联访问ServiceAbility UIAbility关联访问ServiceAbility和UIAbility关联访问ServiceExtensionAbility的方式完全相同。 import common from ohos.app.ability.common; import hilog from o…...

高效解决Visual Studio无法识别到自定义头文件

文章目录 问题解决方案 问题 说明你没有好好配置项目属性 解决方案 把头文件都集中存放到一个文件夹里 之后我会持续更新&#xff0c;如果喜欢我的文章&#xff0c;请记得一键三连哦&#xff0c;点赞关注收藏&#xff0c;你的每一个赞每一份关注每一次收藏都将是我前进路…...

[数据集][目标检测]道路行人车辆坑洞锥形桶检测数据集VOC+YOLO格式6275张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6275 标注数量(xml文件个数)&#xff1a;6275 标注数量(txt文件个数)&#xff1a;6275 标注…...

风险与收益

风险与收益 影响资产需求的主要因素财富总量预期收益率资产的流动性影响流动性的主要因素 风险 如何降低风险系统风险和非系统风险机会集合与有效集合资产组合理论 影响资产需求的主要因素 影响资产需求的主要因素包括&#xff1a;财富总量、预期收益率、资产的流动性和风险。…...

linux服务器安装mysql8

1.下载MYSQL 近几天在linux服务器已安装过2次mysql8&#xff0c;亲测有效&#xff0c;没有遇到任何问题&#xff0c;文档已写的很清楚&#xff0c;按步骤来即可。如果按文档有遇到要使用yum命令的话&#xff0c;需要服务器开通外网。 1.1官网下载 进入官网下拉到最后&#x…...

亚信安全荣获2023年度5G创新应用评优活动两项大奖

近日&#xff0c;“关于2023 年度5G 创新应用评优活动评选结果”正式公布&#xff0c;亚信安全凭借在5G安全领域的深厚积累和创新实践&#xff0c;成功荣获“5G技术创新的优秀代表”和“5G应用创新的杰出实践”两项大奖。 面向异构安全能力的5G安全自动化响应系统 作为5G技术创…...

linux之忘记root密码

一&#xff0c;开机到如下地方按下e进入紧急模式 然后再如下位置输入init/bin/bash 然后Ctrlx 二&#xff0c; 修改密码 以上操作分别为 1&#xff09;&#xff0c;重新挂载根目录 mount -o remount,rw / 2&#xff09;&#xff0c;修改密码 passwd root 3&#xff09;&a…...

jspm智能仓储系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…...

深入理解数据结构(3):栈和队列详解

文章主题&#xff1a;顺序表和链表详解&#x1f331;所属专栏&#xff1a;深入理解数据结构&#x1f4d8;作者简介&#xff1a;更新有关深入理解数据结构知识的博主一枚&#xff0c;记录分享自己对数据结构的深入解读。&#x1f604;个人主页&#xff1a;[₽]的个人主页&#x…...

单例设计模式(3)

单例模式&#xff08;3&#xff09; 实现集群环境下的分布式单例类 如何理解单例模式中的唯一性&#xff1f; 单例模式创建的对象是进程唯一的。以springboot应用程序为例&#xff0c;他是一个进程&#xff0c;可能包含多个线程&#xff0c;单例代表在这个进程的某个类是唯一…...

将jupyter notebook文件导出为pdf(简单有效)

1.打开jupyter notebook笔记&#xff1a; 2.点击file->print Preview 3.在新打开的页面右键打印 4.另存为PDF 5.保存即可 6.pdf效果 &#xff08;可能有少部分图片显示不了&#xff09; 网上也有其他方法&#xff0c;比如将其转换为.tex再转为PDF等&#xff0c;但个人觉…...

使用INSERT INTO ... ON DUPLICATE KEY UPDATE批量插入更新导入excel数据的实践场景应用

INSERT INTO ... ON DUPLICATE KEY UPDATE 是 MySQL 中的一个非常有用的语法&#xff0c;它允许你在插入新记录时&#xff0c;如果记录的唯一键&#xff08;如主键或唯一索引&#xff09;已存在&#xff0c;则执行更新操作而不是插入。这可以帮助你避免在插入数据时产生的重复键…...

AJAX-项目优化(目录、基地址、token、请求拦截器)

目录管理 基地址存储 在utils/request.js配置axios请求基地址 作用&#xff1a;提取公共前缀地址&#xff0c;配置后axios请求时都会baseURLurl 填写API的公共前缀后&#xff0c;将js文件导入到html文件中 <script src"../../utils/request.js"></script&…...

SQLite中的动态内存分配(五)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite中的原子提交&#xff08;四&#xff09; 下一篇:自己编译SQLite或将SQLite移植到新的操作系统&#xff08;六&#xff09; ​概述 SQLite使用动态内存分配来获得 用于存储各种对象的内存 &#xff08;例如…...

快速上手Spring Cloud 十一:微服务架构下的安全与权限管理

快速上手Spring Cloud 一&#xff1a;Spring Cloud 简介 快速上手Spring Cloud 二&#xff1a;核心组件解析 快速上手Spring Cloud 三&#xff1a;API网关深入探索与实战应用 快速上手Spring Cloud 四&#xff1a;微服务治理与安全 快速上手Spring Cloud 五&#xff1a;Spring …...

如何简化多个 if 的判断结构

多少算太多&#xff1f; 有些人认为数字就是一&#xff0c;你应该总是用至少一个三元运算符来代替任何单个 if 语句。我并不这样认为&#xff0c;但我想强调一些摆脱常见的 if/else 意大利面条代码的方法。 我相信很多开发人员很容易陷入 if/else 陷阱&#xff0c;不是因为其…...

发掘服务器硬件优势:怎样有效管理、维护、更新

1. 概述 服务器是许多信息技术的核心&#xff0c;通过提供计算和存储资源&#xff0c;以用于企业和机构的数据处理和存储。服务器硬件也是服务器的核心组成部分&#xff0c;在服务器架构和配置中扮演着重要角色。 服务器硬件的优势&#xff1a; - 提供更高的性能和处理能力。…...

SD卡备份和烧录ubuntu20.04镜像

设备及系统&#xff1a;nuc幻影峡谷工控机&#xff0c;ubuntu20.04&#xff0c;树莓派4B&#xff0c;SD卡读卡器 一、确定SD卡设备号的两种方法 方法1&#xff1a; 将有ubuntu镜像的SD卡插入读卡器&#xff0c;再将读卡器插入电脑主机&#xff0c;在 工具 中打开 磁盘&#…...

短视频账号矩阵系统/开发 -- -- -- 蒙太奇算法上线

短视频账号矩阵系统&#xff0c;短视频矩阵系统开发3年技术之路&#xff0c;目前已经在技术竞品出沉淀出来&#xff0c;近期技术迭代的新的功能同步喽&#xff1a; php7.4版本&#xff0c;自研框架&#xff0c;有开发文档&#xff0c;类laravel框架 近期剪辑迭代的技术算法&am…...

Docker Stack(堆栈) 部署多服务集群,多服务编排

1、Docker Stack简介 Docker Stack(堆栈) 是在 Swarm 上管理服务堆栈的工具。而在以前文章docker swarm集群搭建 介绍的 Docker Swarm 只能实现对单个服务的简单部署&#xff0c;于是就引出了Docker Stack。 上面我们介绍到 docker-compose&#xff1a;可以在一台机器上使用…...

全国青少年软件编程(Scratch)等级考试二级考试真题2023年12月——持续更新.....

青少年软件编程(图形化)等级考试试卷(二级) 分数:100 题数:37 一、单选题(共25题,共50分) 1.在制作推箱子游戏时,地图是用数字形式储存在电脑里的,下图是一个推箱子地图,地图表示如下: 第一行(111111) 第二行(132231) 第三行(126621) 第四行( ) 第五行(152…...

python基础——异常捕获【try-except、else、finally】

&#x1f4dd;前言&#xff1a; 这篇文章主要介绍一下python基础中的异常处理&#xff1a; 1&#xff0c;异常 2&#xff0c;异常的捕获 3&#xff0c;finally语句 &#x1f3ac;个人简介&#xff1a;努力学习ing &#x1f4cb;个人专栏&#xff1a;C语言入门基础以及python入门…...

JAVA面试大全之JVM和调优篇

目录 1、类加载机制 1.1、类加载的生命周期? 1.2、类加载器的层次? 1.3、Class.forName()和ClassLoader.loadClass()区别?...

数据可视化-ECharts Html项目实战(8)

在之前的文章中&#xff0c;我们学习了如何设置散点图涟漪效果与仪表盘动态指针效果。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢 今天的文章&#xff0c;会…...

JavaSE:继承和多态(下篇)

目录 一、前言 二、多态 &#xff08;一&#xff09;多态的概念 &#xff08;二&#xff09;多态实现条件 &#xff08;三&#xff09;多态的优缺点 三、重写 &#xff08;一&#xff09;重写的概念 &#xff08;二&#xff09;重写的规则 &#xff08;三&#xff09;重…...

springboot+mybatis项目集成p6spy输出格式化sql日志

本文背景:公司项目框架是基于springboot+mybatis的web项目,由于鄙人在使用过程中发现打印的mybatis日志每次都要粘贴出来,然后再用在线工具的格式化填充参数,很不方便,最近发现那个在线的工具打不开了,更不方便了,因此想有没有直接可以输出的填充好参数的sql语句,当然i…...

yarn安装和使用及与npm的区别

一、yarn安装和使用 要安装和使用yarn&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装Node.js&#xff1a;首先&#xff0c;您需要在您的计算机上安装Node.js。您可以从Node.js的官方网站&#xff08;https://nodejs.org/en/download/&#xff09;下载并安装适用于您…...

【3D-GS】Gaussian Splatting SLAM——基于3D Gaussian Splatting的全网最详细的解析

【3D-GS】Gaussian Splatting SLAM——基于3D Gaussian Splatting的定SLAM 3D-GS 与 Nerf 和 Gaussian Splatting1. 开山之作 Nerf2. 扛鼎之作 3D Gaussian Splatting2.1 什么是3D高斯?高斯由1D推广到3D的数学推导2.2 什么是光栅化?2.3 什么是Splatting?2.4 什么是交叉优化?…...

推荐多样性 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C++ 题目描述 推荐多样性需要从多个列表中选择元素,一次性要返回N屏数据(窗口数量),每屏展示K个元素(窗口大小),选择策略: 各个列表元素需要做穿插处理,即先从第一个列表中为每屏选择一个元素,再从第二个列表…...

wordpress sns/网站seo搜索引擎优化教程

2019独角兽企业重金招聘Python工程师标准>>> 相对和绝对路径 绝对路径&#xff1a; 路径的写法一定由根目录“/”写起。例如 /usr/local/mysql 这就是绝对路径。 绝对路径不管在那个目录下都能进入访问&#xff01; 相对路径&#xff1a; 路径的写法不是由根目录“/…...

宣传册样式/无锡网站建设方案优化

LaTex说起LaTex&#xff0c;又会扯出Tex、MikTeX、CJK等一系列东西。这并不是我们关注的重点&#xff0c;然而如果你有时间&#xff0c;可以当个睡前故事看看这篇文章。我们只需要知道:LaTex有一套自成体系的语法&#xff0c;常用于科研生产、试卷等文档排版。支持复杂公式&…...

网站海外推广/营销案例分析报告模板

域控蓝屏重启&#xff0c;蓝屏代码为&#xff1a;c00002e2蓝屏重启后会自动进入修复模式&#xff0c;在修复模式下选择疑难解答-->高级选项-->启动设置&#xff0c;重启进入安全模式选择界面&#xff0c;选择从 目录修复服务 启动。使用本机计算机管理员账号密码登录服务…...

张浦专业做网站/西安百度推广代运营

http://www.infoq.com/cn/articles/HIgh-Performance-Parsers-in-Java-V2?utm_sourceinfoq&utm_mediumpopular_links_homepage...

懂的建设网站/企业网站排名优化方案

实验报告课程Java语言程序设计实验名称第八章 Swing图形用户界面程序设计实验任务(三)第页专业班级学号__ __ 姓名实验日期&#xff1a;2010 年11 月9 日报告退发(订正、重做)一、实验目的?布局管理器的使用二、实验环境1、微型计算机一台2、DOS或WINDOWS操作系统&#xff0c;…...

wordpress 自动邮件/2022最近十大的新闻热点

一、多进程 1.主进程和子进程 多任务处理&#xff1a;使得计算机可以同时处理多个任务听歌的同时QQ聊天、办公、下载文件 程序执行就是一个进程 主程序&#xff08;就是主进程&#xff09;中可以包含很多的其他进程。在主进程中添加了子进程&#xff0c;这样每个子进程可以在不…...