【JVM详解二】常量池
一、常量池概述
- class文件常量池
- 运行时常量池
- 字符串常量池
- 基本类型包装类常量池

- 每个 class 的字节码文件中都有一个常量池,里面是编译后即知的该 class 会用到的字面量与符号引用,这就是 class 文件常量池。JVM加载 class ,会将其类信息,包括 class 文件常量池置于方法区中。
- class 类信息及其 class 文件常量池是字节码的二进制流,它代表的是一个类的静态存储结构,JVM加载类时,需要将其转换为方法区中的 java.lang.Class 类的对象实例;同时,会将 class 文件常量池中的内容导入运行时常量池。
- 运行时常量池中的常量对应的内容只是字面量,比如一个"字符串",它还不是 String 对象;当 Java 程序在运行时执行到这个"字符串"字面量时,会去字符串常量池里找该字面量的对象引用是否存在,存在则直接返回该引用,不存在则在Java堆里创建该字面量对应的 String 对象,并将其引用置于字符串常量池中,然后返回该引用。
- Java的基本数据类型中,除了两个浮点数类型,其他的基本数据类型都在各自内部实现了常量池,但都在[-128~127]这个范围内。
二、class文件常量池
java的源代码 .java 文件在编译之后会生成 .class 文件,class 文件需要严格遵循 JVM 规范才能被 JVM 正常加载,它是一个二进制字节流文件,里面包含了class文件常量池的内容。
class文件常量池诞生于编译时,存在于class文件中,存放符号引用和字面量。

2.1 查看一个class文件内容
jdk 提供了 javap 命令,用于对class文件进行反汇编,输出类相关信息。该命令用法如下:
用法: javap <options> <classes>
其中, 可能的选项包括:-help --help -? 输出此用法消息-version 版本信息-v -verbose 输出附加信息-l 输出行号和本地变量表-public 仅显示公共类和成员-protected 显示受保护的/公共类和成员-package 显示程序包/受保护的/公共类和成员 (默认)-p -private 显示所有类和成员-c 对代码进行反汇编-s 输出内部类型签名-sysinfo 显示正在处理的类的系统信息 (路径, 大小, 日期, MD5 散列)-constants 显示最终常量-classpath <path> 指定查找用户类文件的位置-cp <path> 指定查找用户类文件的位置-bootclasspath <path> 覆盖引导类文件的位置
例如,我们可以编写一个简单的类,如下:
public class Student {private final String name = "张三";private final int entranceAge = 18;private String evaluate = "优秀";private int scores = 95;private Integer level = 5;public String getEvaluate() {return evaluate;}public void setEvaluate(String evaluate) {String tmp = "+";this.evaluate = evaluate + tmp;}public int getScores() {return scores;}public void setScores(int scores) {final int base = 10;System.out.println("base:" + base);this.scores = scores + base;}public Integer getLevel() {return level;}public void setLevel(Integer level) {this.level = level;}
}
对其进行编译和反汇编:
javac Student.java
javap -v Student.class
# over
得到以下反汇编结果:
Classfile /home/work/sources/open_projects/lib-zc-crypto/src/test/java/Student.classLast modified 2021-1-4; size 1299 bytesMD5 checksum 06dfdad9da59e2a64d62061637380969Compiled from "Student.java"
public class Studentminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #19.#48 // java/lang/Object."<init>":()V#2 = String #49 // 张三#3 = Fieldref #18.#50 // Student.name:Ljava/lang/String;#4 = Fieldref #18.#51 // Student.entranceAge:I#5 = String #52 // 优秀#6 = Fieldref #18.#53 // Student.evaluate:Ljava/lang/String;#7 = Fieldref #18.#54 // Student.scores:I#8 = Methodref #55.#56 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;#9 = Fieldref #18.#57 // Student.level:Ljava/lang/Integer;#10 = String #58 // +#11 = Class #59 // java/lang/StringBuilder#12 = Methodref #11.#48 // java/lang/StringBuilder."<init>":()V#13 = Methodref #11.#60 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#14 = Methodref #11.#61 // java/lang/StringBuilder.toString:()Ljava/lang/String;#15 = Fieldref #62.#63 // java/lang/System.out:Ljava/io/PrintStream;#16 = String #64 // base:10#17 = Methodref #65.#66 // java/io/PrintStream.println:(Ljava/lang/String;)V#18 = Class #67 // Student#19 = Class #68 // java/lang/Object#20 = Utf8 name#21 = Utf8 Ljava/lang/String;#22 = Utf8 ConstantValue#23 = Utf8 entranceAge#24 = Utf8 I#25 = Integer 18#26 = Utf8 evaluate#27 = Utf8 scores#28 = Utf8 level#29 = Utf8 Ljava/lang/Integer;#30 = Utf8 <init>#31 = Utf8 ()V#32 = Utf8 Code#33 = Utf8 LineNumberTable#34 = Utf8 getEvaluate#35 = Utf8 ()Ljava/lang/String;#36 = Utf8 setEvaluate#37 = Utf8 (Ljava/lang/String;)V#38 = Utf8 getScores#39 = Utf8 ()I#40 = Utf8 setScores#41 = Utf8 (I)V#42 = Utf8 getLevel#43 = Utf8 ()Ljava/lang/Integer;#44 = Utf8 setLevel#45 = Utf8 (Ljava/lang/Integer;)V#46 = Utf8 SourceFile#47 = Utf8 Student.java#48 = NameAndType #30:#31 // "<init>":()V#49 = Utf8 张三#50 = NameAndType #20:#21 // name:Ljava/lang/String;#51 = NameAndType #23:#24 // entranceAge:I#52 = Utf8 优秀#53 = NameAndType #26:#21 // evaluate:Ljava/lang/String;#54 = NameAndType #27:#24 // scores:I#55 = Class #69 // java/lang/Integer#56 = NameAndType #70:#71 // valueOf:(I)Ljava/lang/Integer;#57 = NameAndType #28:#29 // level:Ljava/lang/Integer;#58 = Utf8 +#59 = Utf8 java/lang/StringBuilder#60 = NameAndType #72:#73 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#61 = NameAndType #74:#35 // toString:()Ljava/lang/String;#62 = Class #75 // java/lang/System#63 = NameAndType #76:#77 // out:Ljava/io/PrintStream;#64 = Utf8 base:10#65 = Class #78 // java/io/PrintStream#66 = NameAndType #79:#37 // println:(Ljava/lang/String;)V#67 = Utf8 Student#68 = Utf8 java/lang/Object#69 = Utf8 java/lang/Integer#70 = Utf8 valueOf#71 = Utf8 (I)Ljava/lang/Integer;#72 = Utf8 append#73 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;#74 = Utf8 toString#75 = Utf8 java/lang/System#76 = Utf8 out#77 = Utf8 Ljava/io/PrintStream;#78 = Utf8 java/io/PrintStream#79 = Utf8 println
{方法信息,此处省略...
}
SourceFile: "Student.java"
其中的 Constant pool 就是 class 文件常量池,使用 # 加数字标记每个“常量”。
2.2 class文件常量池的内容
class 文件常量池存放的是该 class 编译后即知的,在运行时将会用到的各个“常量”。注意这个常量不是编程中所说的 final 修饰的变量,而是字面量和符号引用,如下图所示:

2.2.1 字面量
字面量大约相当于Java代码中的双引号字符串和常量的实际的值,包括:
1)文本字符串
即代码中用双引号包裹的字符串部分的值。
例如刚刚的例子中,有三个字符串:"张三","优秀","+",它们在class文件常量池中分别对应:
#49 = Utf8 张三
#52 = Utf8 优秀
#58 = Utf8 +
2)用final修饰的成员变量的值
例如,private static final int entranceAge = 18;
这条语句定义了一个final常量entranceAge,它的值是18,对应在class文件常量池中就有:
#25 = Integer 18
注意,只有final修饰的成员变量如entranceAge,才会在常量池中存在对应的字面量。而非final的成员变量scores,以及局部变量base(即使使用final修饰了),它们的字面量都不会在常量池中定义。
2.2.2 符号引用
1)类和接口的全限定名
例如:
#11 = Class #59 // java/lang/StringBuilder
#59 = Utf8 java/lang/StringBuilder
2)方法的名称和描述符
例如:
#38 = Utf8 getScores
#39 = Utf8 ()I#40 = Utf8 setScores
#41 = Utf8 (I)V
以及这种对其他类的方法的引用:
#8 = Methodref #55.#56 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;#55 = Class #69 // java/lang/Integer
#69 = Utf8 java/lang/Integer#56 = NameAndType #70:#71 // valueOf:(I)Ljava/lang/Integer;
#70 = Utf8 valueOf
#71 = Utf8 (I)Ljava/lang/Integer;
3)字段的名称和描述符
例如:
#3 = Fieldref #18.#50 // Student.name:Ljava/lang/String;#18 = Class #67 // Student
#67 = Utf8 Student#50 = NameAndType #20:#21 // name:Ljava/lang/String;
#20 = Utf8 name
#21 = Utf8 Ljava/lang/String;
以及这种局部变量:
#64 = Utf8 base:10
三、运行时常量池
JVM在加载某个 class 的时候,需要完成以下任务:
- 通过该class的全限定名来获取它的二进制字节流,即读取其字节码文件。其内容包括在上文class文件常量池中介绍的class文件常量池。
- 将读入的字节流从静态存储结构转换为方法区中的运行时的数据结构。
- 在Java堆中生成该 class 对应的类对象,代表该 class 原信息。这个类对象的类型是 java.lang.Class,它与普通对象不同的地方在于,普通对象一般都是在 new 之后创建的,而类对象是在类加载的时候创建的,且是单例。
上述过程的第二步,就包含了将 class 文件常量池内容导入运行时常量池。class 文件常量池是一个 class 文件对应一个常量池,而运行时常量池只有一个,多个 class 文件常量池中的相同字符串只会对应运行时常量池中的一个字符串。
运行时常量池除了导入 class 文件常量池的内容,还会保存符号引用对应的直接引用(实际内存地址)。这些直接引用是JVM在类加载之后的链接(验证、准备、解析)阶段从符号引用翻译过来的。
此外,运行时常量池具有动态性的特征,它的内容并不是全部来源与编译后的 class 文件,在运行时也可以通过代码生成常量并放入运行时常量池。比如 String.intern() 方法(String.intern()方法的分析见下文)。
要注意的是,运行时常量池中保存的“常量”依然是字面量和符号引用。比如字符串,这里放的仍然是单纯的文本字符串,而不是 String 对象。

四、字符串常量池
字符串常量池,是 JVM 用来维护字符串实例的一个引用表。在 HotSpot 虚拟机中,它被实现为一个全局的 StringTable ,底层是一个 c++ 的 hashtable 。它将字符串的字面量作为 key ,实际堆中创建的 String 对象的引用作为 value 。
字符串常量池在逻辑上属于方法区,但 JDK1.7 开始,就被挪到了堆区。
String 的字面量被导入 JVM 的运行时常量池时,并不会马上试图在字符串常量池加入对应 String 的引用,而是等到程序实际运行时,要用到这个字面量对应的 String 对象时,才会去字符串常量池试图获取或者加入 String 对象的引用。因此它是懒加载的。
如前所述,class 文件常量池和运行时常量池中,都没有直接存储字面量对应的实际对象,比如 String 对象。那么 String 对象到底是什么时候在哪里创建的呢?

4.1 创建字符串对象的方式
4.1.1 字面量赋值
直接用双引号字面值的方式创建字符串。
String str1 = "test";
String str2 = "test";
//str1 == str2 ? true
System.out.println("str1 == str2 ? "+ (str1 == str2));
当Java虚拟机启动成功后,上面的字符串"test"的字面量已经进入运行时常量池;
然后主线程开始运行,执行到 String str1 = “test"; 这条语句时,JVM会根据运行时常量池中的这个字面量去字符串常量池寻找其中是否有该字面量对应的 String 对象的引用,注意是引用。 如果没找到,就会去 Java 堆创建一个值为 “test" 的 String 对象,并将该对象的引用保存到字符串常量池,然后返回该引用;如果找到了,说明之前已经有其他语句通过相同的字面量赋值创建了该 String 对象,直接返回引用即可。
接着执行到 String str2 = “test"; 这条语句,JVM 成功找到上一步生成的 String 对象的引用。所以 str1 == str2 返回 true。
4.1.2 new String 创建字符串
使用new String 创建字符串,会先在常量池中创建,再在堆中创建。
String str3 = new String("tony");
String str4 = "tony";
//str3 == str4 ? false
System.out.println("str3 == str4 ? " + (str3 == str4));
- 第一句中JVM拿字面量 “tony" 去字符串常量池试图获取其对应 String 对象的引用,因为是首次执行,所以没找到,于是在堆中创建了一个 “tony" 的 String 对象,并将其引用保存到字符串常量池中,然后返回;
- 返回之后,因为new的存在,JVM又在堆中创建了与 “tony" 等值的另一个 String 对象。
- 因此这条语句创建了两个 String 对象,它们值相等,都是 “tony" ,但是引用(内存地址)不同,所以 str3 == str4 结果是false。
4.1.3 String.intern() 方法
String.intern() 是一个 native (本地) 方法,用来处理字符串常量池中的字符串对象引用。它的工作流程可以概括为以下两种情况:
- 常量池中已有相同内容的字符串对象:如果字符串常量池中已经有一个与调用 intern() 方法的字符串内容相同的 String 对象,intern() 方法会直接返回常量池中该对象的引用。
- 常量池中没有相同内容的字符串对象:如果字符串常量池中还没有一个与调用 intern() 方法的字符串内容相同的对象,intern() 方法会将当前字符串对象的引用添加到字符串常量池中,并返回该引用。
总结:
- intern() 方法的主要作用是确保字符串引用在常量池中的唯一性。
- 当调用 intern() 时,如果常量池中已经存在相同内容的字符串,则返回常量池中已有对象的引用;否则,将该字符串添加到常量池并返回其引用。
// 创建一个新的 "Java" 对象,并把该"Java" 对象的引用添加到字符串常量池,s1 指向该引用
String s1 = "Java";
// s2 也指向字符串常量池中 "Java" 对象的引用,和 s1 是同一个对象
String s2 = s1.intern();
// 在堆中创建一个新的 "Java" 对象,s3 指向它
String s3 = new String("Java");
// s4 指向字符串常量池中的 "Java" 对象的引用,和 s1 是同一个对象
String s4 = s3.intern();
// s1 和 s2 指向的是同一个常量池中的对象
System.out.println(s1 == s2); // true
// s3 指向堆中的对象,s4 指向字符串常量池中的对象引用,所以不同
System.out.println(s3 == s4); // false
// s1 和 s4 都指向常量池中的同一个对象
System.out.println(s1 == s4); // true
对于第14行 s1 == s4 要注意,JDK1.6和JDK1.7开始,String.intern()的执行逻辑是不一样的。
- JDK1.6 以前 intern() 可以查找调用该 intern 的对象是否存在字符串常量池,如果存在 返回其引用;如果 不存在,则添加进去并返回引用;
- JDK1.7及以后 intern() 查找是否存在 如果存在 则返回其引用;但是,如果字符串常量池不存在(堆区一定存在,不存在就无法调用该方法),那么就将该堆区对象的引用加入字符串常量池。
因此对于第14行 s1 == s4 ,如果是JDK1.6及以前的版本,结果就是false;而如果是JDK1.7开始的版本,结果就是true。
4.1.4 new String 相加
String str5 = new String("good") + new String("morning");
str5.intern();
String str6 = "goodmorning";
//str5 == str6 ? true str5 == str5.intern() ? true
System.out.println("str5 == str6 ? " + (str5 == str6) + " str5 == str5.intern() ? " + (str5 == str5.intern()));
第一句会分别把不在常量池的"good"和"morning"两个常量对象加入常量池,拼接起来"goodmorning"不在常量池,而"goodmorning"并不会在常量池中创建常量或引用。str5.intern()检查常量池是否有字符串"goodmorning",没有,把引用添加到常量池中,str6检查常量池有字符串"goodmorning",返回它的引用,所以两个判断的结果都是true。
String str5 = new String(“good”) + new String(“morning”) 被JVM编译优化后后如下:
String str5 = (new StringBuilder()).append(new String("good")).append(new String("morning")).toString();
底层是一个StringBuilder在进行把两个对象拼接在一起,最后栈中str5指向堆中的"goodmorning",其实是StringBuilder对象:

4.2 字符串常量池是否会被GC
字符串常量池本身不会被GC,但其中保存的引用所指向的 String 对象们是可以被回收的。否则字符串常量池总是"只进不出",那么很可能会导致内存泄露。
在 HotSpot 的字符串常量池实现 StringTable 中,提供了相应的接口用于支持GC,不同的GC策略会在适当的时候调用它们。一般实在Full GC的时候,额外调用StringTable的对应接口做可达性分析,将不可达的String对象的引用从StringTable中移除掉并销毁其指向的String对象。
五、封装类常量池
除了字符串常量池,Java 的基本类型的封装类大部分也都实现了常量池。包括 Byte、Short、Integer、Long、Character、Boolean,注意,浮点数据类型Float、Double是没有常量池的。
封装类的常量池是在各自内部类中实现的,比如 IntegerCache(Integer的内部类),自然也位于堆区。
要注意的是,这些常量池是有范围的:
- Byte , Short , Integer , Long : [-128~127]
- Character : [0~127]
- Boolean : [True, False]
例如下面的代码,注意其结果:
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2); //trueInteger i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4); //falseInteger i5 = -128;
Integer i6 = -128;
System.out.println(i5 == i6); //trueInteger i7 = -129;
Integer i8 = -129;
System.out.println(i7 == i8); //false
相关文章:

【JVM详解二】常量池
一、常量池概述 JVM的常量池主要有以下几种: class文件常量池运行时常量池字符串常量池基本类型包装类常量池 它们相互之间关系大致如下图所示: 每个 class 的字节码文件中都有一个常量池,里面是编译后即知的该 class 会用到的字面量与符号引…...

w200基于spring boot的个人博客系统的设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...

【算法】快速排序算法的实现:C 和 C++ 版本
1. 算法简介 快速排序(Quick Sort)是由英国计算机科学家霍尔(C.A.R. Hoare)在1960年提出的一种高效的排序算法。它采用了分治法(Divide and Conquer)策略,通常具有很好的性能。在平均情况下,快速排序的时间复杂度为 O(n log n),但在最坏情况下可能退化为 O(n^2),不过…...

前沿科技一览未来发展趋势
脑机接口技术在医疗康复领域有了新进展。这技术让机器读懂大脑信号,帮助病人找回身体功能。 比如,瘫痪人士可以用它来控制假肢。在美国,一名瘫痪者通过这个技术,能用自己意念控制机械臂,喝到饮料。这种技术对提升患者…...

js滚动到页面最底部
setTimeout(()> { //延后执行,等页面渲染结束let container document.querySelector(.raise-flag-content); //找到当前divif (container) {container.scrollTop container.scrollHeight - (container.clientHeight - 400 );}})container.scrollTop container…...

视觉硬件选型和算法选择(CNN)
基础知识 什么是机械视觉: 机械视觉是一种利用机器代替人眼来进行测量和判断的技术,通过光学系统、图像传感器等设备获取图像,并运用图像处理和分析算法来提取信息,以实现对目标物体的识别、检测、测量和定位等功能。 机械视觉与人类视觉有什…...

Mybatis篇
1,什么是Mybatis ( 1 )Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁…...

【Python】元组
个人主页:GUIQU. 归属专栏:Python 文章目录 1. 元组的本质与基础概念1.1 不可变序列的意义1.2 元组与数学概念的联系 2. 元组的创建方式详解2.1 标准创建形式2.2 单元素元组的特殊处理2.3 使用 tuple() 函数进行转换 3. 元组的基本操作深入剖析3.1 索引操…...

【AI实践】deepseek支持升级git
当前Windows 11 WSL的git是2.17,Android Studio提示需要升级到2.19版本 网上找到指导文章 安装git 2.19.2 cd /usr/src wget https://www.kernel.org/pub/software/scm/git/git-2.19.2.tar.gz tar xzf git-2.19.2.tar.gz cd git-2.19.2 make prefix/usr/l…...

【AI实践】Cursor上手-跑通Hello World和时间管理功能
背景 学习目的:熟悉Cursor使用环境,跑通基本开发链路。 本人背景:安卓开发不熟悉,了解科技软硬件常识 实践 基础操作 1,下载安装安卓Android Studio 创建一个empty project 工程,名称为helloworld 2&am…...

Redis数据库(二):Redis 常用的五种数据结构
Redis 能够做到高性能的原因主要有两个,一是它本身是内存型数据库,二是采用了多种适用于不同场景的底层数据结构。 Redis 常用的数据结构支持字符串、列表、哈希表、集合和有序集合。实现这些数据结构的底层数据结构有 6 种,分别是简单动态字…...

【计组】实验五 J型指令设计实验
目录 一、实验目的 二、实验环境 三、实验原理 四、实验任务 代码 一、实验目的 1. 理解MIPS处理器指令格式及功能。 2. 掌握lw, sw, beq, bne, lui, j, jal指令格式与功能。 3. 掌握ModelSim和ISE\Vivado工具软件。 4. 掌握基本的测试代码编写和FPGA开发板使用方法。 …...

ubuntu 本地部署deepseek r1 蒸馏模型
本文中的文件路径或网络代理需要根据自身环境自行删改 一、交互式chat页面 1.1 open-webui 交互窗口部署:基于docker安装,且支持联网搜索 Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 AI 平台,旨在完全离线操作。它支持各种 LLM…...

RestTemplate Https 证书访问错误
错误信息 resttemplate I/O error on GET request for “https://21.24.6.6:9443/authn-api/v5/oauth/token”: java.security.cert.CertificateException: No subject alternative names present; nested exception is javax.net.ssl.SSLHandshakeException: java.security.c…...

MySQL内存使用率高且不释放问题排查与总结
背景 生产环境mysql 5.7内存占用超过90%以上,且一直下不来。截图如下: 原因分析 1、确定mysql具体的占用内存大小,通过命令:cat /proc/Mysql进程ID/status查看 命令执行后的结果比较多(其他参数的含义想了解可参考这…...

mysql8 从C++源码角度看sql生成抽象语法树
在 MySQL 8 的 C 源码中,SQL 语句的解析过程涉及多个步骤,包括词法分析、语法分析和抽象语法树(AST)的生成。以下是详细的解析过程和相关组件的描述: 1. 词法分析器(Lexer) MySQL 使用一个称为…...

【DeepSeek】DeepSeek概述 | 本地部署deepseek
目录 1 -> 概述 1.1 -> 技术特点 1.2 -> 模型发布 1.3 -> 应用领域 1.4 -> 优势与影响 2 -> 本地部署 2.1 -> 安装ollama 2.2 -> 部署deepseek-r1模型 1 -> 概述 DeepSeek是由中国的深度求索公司开发的一系列人工智能模型,以其…...

【C++】多态原理剖析
目录 1.虚表指针与虚表 2.多态原理剖析 1.虚表指针与虚表 🍪类的大小计算规则 一个类的大小,实际就是该类中成员变量之和,需要注意内存对齐空类:编译器给空类一个字节来唯一标识这个类的对象 对于下面的Base类,它的…...

【Rust自学】20.4. 结语:Rust学习一阶段完成+附录
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 20.4.1. 总结 Rust初级学习之旅终于完成了!恭喜! 包括这篇文章,我们使用了110篇文章来学习Rust。 真…...

pytorch引用halcon写数据集
****加粗样式虽然啰嗦一点,但好歹halcon自己熟悉,不会忘记,用os 和 pil会导致脑子记得东西太多 import halcon as ha import torch from torch.utils.data import Datasetpath0 rE:\BaiduNetdiskDownload\cell class MyDataset(Dataset):de…...

让文物“活”起来,以3D数字化技术传承文物历史文化!
文物,作为不可再生的宝贵资源,其任何毁损都是无法逆转的损失。然而,当前文物保护与修复领域仍大量依赖传统技术,同时,文物管理机构和专业团队的力量相对薄弱,亟需引入数字化管理手段以应对挑战。 积木易搭…...

aarch64 Ubuntu20.04 安装docker
安装 docker 依赖项:sudo apt-get update sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release添加 Docker GPG 密钥:curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyr…...

JAVA:CloseableHttpClient 进行 HTTP 请求的技术指南
1、简述 CloseableHttpClient 是 Apache HttpComponents 提供的一个强大 HTTP 客户端库。它允许 Java 程序与 HTTP/HTTPS 服务交互,可以发送 GET、POST 等各种请求类型,并处理响应。该库广泛用于 REST API 调用、文件上传和下载等场景。 2、特性 Close…...

Mac上搭建k8s环境——Minikube
1、在mac上安装Minikube可执行程序 brew cask install minikub 安装后使用minikube version命令查看版本 2、安装docker环境 brew install --cask --appdir/Applications docker #安装docker open -a Docker #启动docker 3、安装kubectl curl -LO https://storage.g…...

经典排序算法复习----C语言
经典排序算法复习 分类 交换类 冒泡快排 分配类 计数排序基数排序 选择类 选择排序 堆排序 归并类 归并排序 插入类 直接插入排序 希尔排序 折半插入排序 冒泡排序 基于交换。每一轮找最大值放到数组尾部 //冒泡排序 void bubSort(int* arr,int size){bool sorte…...

自动驾驶数据集三剑客:nuScenes、nuImages 与 nuPlan 的技术矩阵与生态协同
目录 1、引言 2、主要内容 2.1、定位对比:感知与规划的全维覆盖 2.2、数据与技术特性对比 2.3、技术协同:构建全栈研发生态 2.4、应用场景与评估体系 2.5、总结与展望 3、参考文献 1、引言 随着自动驾驶技术向全栈化迈进,Motional 团…...

[LUA ERROR] bad light userdata pointer
Cocos2d项目,targetSdkVersion30,在 android 13 设备运行报错: [LUA ERROR] bad light userdata pointer ,导致黑屏。 参考 cocos2dx 适配64位 arm64-v8a 30 lua 提示 bad light userdata pointer 黑屏-CSDN博客的方法 下载最新的Cocos2dx …...

【Java八股】JVM
JVM 1. jvm内存区域分为哪些部分 线程私有的:程序计数器、虚拟机栈、本地方法栈 程序计数器:指示当前线程执行到的字节码文件的行号,是线程切换后保证线程能恢复到正确的执行位置的关键 虚拟机栈:用于存储方法调用的数据&…...

集成学习(一):从理论到实战(附代码)
一、引言 在机器学习领域,打造一个独立、强大的算法是解决问题的关键。然而,集成学习提供了一种不同的视角:通过组合多个“弱”学习器来创建一个更强大的模型。本文探讨集成学习的思想、方法及其应用。 二、机器学习 vs 集成学习思想 传统…...

Netty:高性能网络应用框架的深度解析
引言 Netty 是由 JBoss 提供的一个开源的 Java NIO 客户端/服务器框架,它用以快速开发网络应用程序,如协议服务器和客户端。它的设计目标是提供异步事件驱动的网络应用程序框架,支持高效的网络通信和数据处理。Netty 在性能、可扩展性、安全…...