HotSpot JVM 中的应用程序/动态类数据共享

news2025/1/19 11:36:37

0.前言

本文的目的是详细讨论 HotSpot JVM 自 JDK 1.5 以来提供的一项功能,该功能可以减少启动时间,但如果在多个 JVM 之间共享相同的类数据共享 (CDS) 存档,则还可以减少内存占用。

1.类数据共享 (CDS)

CDS 的想法是使用特定格式将预处理的类元数据缓存在磁盘上的存档中,以便可以非常快速地加载它们(与从 JAR 文件存储和加载的类相比会快很多)。 CDS 是在 Sun JDK 1.5 中引入的,最初仅适用于 Java HotSpot 客户端 VM 和串行垃圾收集器 (GC)。 在 JDK 9 中,它被扩展为支持 C2 Just-inTime Compiler (JIT) 和其他收集器(例如 Parallel、ParallelOld 和 G1)。 从 JDK 17 开始,它支持 ZGC、G1 GC、串行 GC、并行 GC 和 Shenandoah GC。

CDS 存档仅包含大多数应用程序使用的核心库类。 这些类(从 JDK 17 开始,总共大约 1400 个)由引导类加载器加载,它们属于以下包:java.lang.、java.util.、java.io.、java.nio.、 jdk.internal.、java.security.、java.net.* 等。CDS 存档也称为默认 CDS 存档或静态基础 CDS 存档。

从 JDK 12 (JEP 341) 开始,CDS 存档是在 64 位平台上的 JDK 构建期间通过运行 -Xshare:dump 并使用 G1 GC(默认 GC)创建的。 它使用内置时间生成的默认类列表,并且根据平台位于不同的目录下。

Linux/macOS:

// default CDS archive
$JAVA_HOME/lib/server/classes.jsa

// class list
$JAVA_HOME/lib/classlist

Windows:

// default CDS archive
$JAVA_HOME\\bin\\server\\classes.jsa

// class list
$JAVA_HOME\\bin\\classlist

CDS存档分为7个区域,如下图所示:
在这里插入图片描述
说明:

  • rw – 读写元数据(例如,C++ vtables)
  • ro – 只读元数据和只读表(例如,SymbolTable、StringTable、SystemDictionary)
  • bm – 标记存档内不同区域的所有指针位置的位图
  • ao0 – 打开归档堆空间 0(例如,java 基本类型(例如,Boolean、Char、Float 等)、Klass* 对象(例如,InstanceKlass、TypeArrayKlass*、ObjArrayKlass*))
  • ao1 – 打开归档堆空间 1(可能为空)
  • ca0 – 封闭的归档堆空间 0(例如,内部字符串)
  • ca1 – 封闭的归档堆空间 1(可能为空)

为了更深入地理解(或只是出于好奇),我建议查看 OpenJDK 源代码。

除非指定 -Xshare:off,否则在大多数 JDK 发行版中默认启用 CDS。 当 JVM 启动时,存档会进行内存映射并在多个 JVM 进程之间共享(使用共享文件系统)。 然而,目前只有具有 Compressed{Opps,ClassPointers} 的 G1 GC 可以在启动时映射存档堆区域。 使用不同的 GC(例如 SerialGC)启动 JVM 最终将禁用共享 Java 堆对象。 默认情况下,不会打印此信息,因此要获取它,您必须在启动应用程序时显式指定 -Xlog:cds 选项。

$ java -Xlog:cds -XX:+UseSerialGC -cp <app jar> MyApp

[info][cds] CDS heap data is being ignored. UseG1GC, UseCompressedOops and UseCompressedClassPointers are required.

2.归档在磁盘上的占用空间

存储在 CDS 中的类比存储在 JAR 文件或 JDK 运行时映像中的类大几倍(例如 3 – 5 倍)。 例如,JDK 17 中的默认类列表包含 1399 个类,存档总共约 13,372 KB (~ 13.05MB)。

$ cat $JAVA_HOME/lib/classlist | wc -l
1399

$ ls -l --block-size=1K $JAVA_HOME/lib/server/
-r--r--r-- 1 10668 10668 13372 Dec  7 22:48 classes.jsa

3.应用程序类数据共享(AppCDS)

应用程序类数据共享 (AppCDS) 将 CDS 概念扩展到内置系统类加载器(即应用程序类加载器)和自定义类加载器。 这最初是作为商业 Oracle JDK 功能添加的,但后来成为 OpenJDK 10 (JEP 310) 的一部分。 AppCDS 也称为静态存档。

AppCDS 存档必须显式创建,过程分为三步。

步骤 1:创建 AppCDS 类列表(例如 static-cds.lst)。 可以进行多次试运行来创建此类列表。

$ java -Xshare:off -XX:DumpLoadedClassList=static-cds.lst -cp <app jar> MyApp

如果您打开类列表,您可能会注意到它还包括核心库类(它们是默认 CDS 存档的一部分)。

步骤 2:根据之前创建的类列表创建 AppCDS 存档(例如 static-cds.jsa)

$ java -Xshare:dump -XX:SharedClassListFile=static-cds.lst -XX:SharedArchiveFile=static-cds.jsa -cp <app jar> MyApp

步骤 3:启动应用程序并指定 AppCDS 存档的名称作为参数

$ java -XX:SharedArchiveFile=static-cds.jsa -cp <app jar> MyApp

4.共享基地址

默认情况下,在转储期间,存档会映射到共享基地址 0x800000000。 如果所需的地址空间不可用,地址空间布局随机化 (ASLR) 可能会导致此操作偶尔失败。 为了使 JVM 能够应对此故障,您可以考虑使用 -Xshare:auto 选项运行它,或者(如果这对您的设置有意义;例如,在基准测试期间)甚至禁用 ASLR。

无论哪种方式,在 -Xshare:dump 期间,选项 -XX:SharedBaseAddress=<new_address> 可用于覆盖默认共享基地址或 -XX:SharedBaseAddress=0 以映射到操作系统选定的地址。

将 -Xlog:cds 选项添加到之前步骤 2 中的命令(即创建 AppCDS 存档)会打印存档区域及其基地址:

$ java -Xlog:cds -Xshare:dump -XX:SharedClassListFile=static-cds.lst -XX:SharedArchiveFile=static-cds.jsa -cp <app jar> MyApp 

[info][cds] Dumping shared data to file: 
[info][cds]    static-cds.jsa
[info][cds] Shared file region (rw )  0:  8093376 bytes, addr 0x0000000800000000 file offset 0x00001000 crc 0x5b23ef23
[info][cds] Shared file region (ro )  1: 13016776 bytes, addr 0x00000008007b8000 file offset 0x007b9000 crc 0x12a5a9d7
[info][cds] Shared file region (bm )  2:   381440 bytes, addr 0x0000000000000000 file offset 0x01423000 crc 0x80f2eed3
[info][cds] Shared file region (ca0)  3:   925696 bytes, addr 0x00000007bfc00000 file offset 0x01481000 crc 0x0e32d31c
[info][cds] Shared file region (oa0)  5:   724992 bytes, addr 0x00000007bf800000 file offset 0x01563000 crc 0xc4b5b70d

5.存储临时字符串

如果您正在使用 AppCDS,那么您可能还会有兴趣了解如何使用字符串数据和符号数据增强存档 (JEP 250)。 这可能会进一步减少应用程序的启动时间,特别是在应用程序使用大量字符串的情况下。 然而,创建额外的共享配置文件(包含字符串和符号)并不简单,因此我将尝试在这里简要解释一下。

字符串数据和符号数据可以使用附加到正在运行的 JVM 进程的 jcmd 工具生成:

$ jcmd <PID> VM.stringtable -verbose
$ jcmd <PID> VM.symboltable -verbose

然后,输出必须合并到单个文件(例如 static-cds-shared-strings.cfg),其整体结构如下:

VERSION: 1.0
@SECTION: String
$ jcmd <pid> VM.stringtable -verbose
@SECTION: Symbol
$ jcmd <pid> VM.symboltable -verbose

OpenJDK 源代码中提供了一个示例(用于测试目的)(例如,如果您想查看整体结构)。 Volker Simonis 在他的演讲中详细介绍了相同的功能:HotSpot VM 中的数据共享类。

要使用附加共享配置文件(包括字符串和符号数据)创建 AppCDS 存档,您需要使用以下参数列表启动应用程序:

$ java -Xshare:dump -XX:SharedClassListFile=static-cds.lst -XX:SharedArchiveConfigFile=static-cds-shared-strings.cfg -XX:SharedArchiveFile=static-cds.jsa -cp <app jar> MyApp

这与上面的步骤 3 非常相似,但还使用了 -XX:SharedArchiveConfigFile。

6.动态类数据共享(动态CDS)

动态 CDS 进一步扩展了 AppCDS,以动态允许在 Java 进程结束时进行归档。 该存档也简称为动态存档。 此功能自版本 13 (JEP 350) 起成为 OpenJDK 的一部分

动态 CDS 无需创建类列表(即初始 AppCDS 步骤),从而简化了 AppCDS 存档创建,因此它是一个两步过程。

第 1 步:创建动态 CDS 存档

$ java -XX:ArchiveClassesAtExit=dynamic-cds.jsa -cp <app jar> MyApp

步骤 2:启动应用程序并指定动态 CDS 存档的名称作为参数

$ java -XX:SharedArchiveFile=dynamic-cds.jsa -cp <app jar> MyApp

7.基础层依赖

动态 CDS 存档(隐式)创建在静态基本 CDS 存档(例如,classes.jsa)之上作为顶层存档,并且它使用更少的磁盘空间(因为核心库类不是其中的一部分)。 使用 -Xlog:cds 选项启动应用程序会打印两个存档:

$ java -Xlog:cds -XX:SharedArchiveFile=dynamic-cds.jsa -cp <app jar> MyApp

[info][cds] trying to map $JAVA_HOME/lib/server/classes.jsa
[info][cds] Opened archive $JAVA_HOME/lib/server/classes.jsa

[info][cds] trying to map dynamic-cds.jsa
[info][cds] Opened archive dynamic-cds.jsa

动态CDS存档和静态存档之间的分层依赖关系可以说明如下:
在这里插入图片描述
在此依赖关系链中,静态存档可以是默认 CDS 存档(即,classes.jsa)或自定义 AppCDS 存档(即,静态存档)。 用作基础层存档的 AppCDS 会覆盖默认的 CDS 存档。 动态存档仅提供可在 AppCDS 存档中的类之上加载的附加类。

当您拥有所有应用程序通用的同一组库(例如框架库)时,将 AppCDS 作为基础层中的静态存档可能会很有帮助。 此外,每个应用程序的详细信息都作为顶层存档转储在动态存档中。

8.基于AppCDS存档创建动态CDS存档

要在 AppCDS 存档之上创建动态 CDS 存档(作为非默认静态 CDS),您必须使用以下命令启动 JVM:

$ java -XX:SharedArchiveFile=static-cds.jsa -XX:ArchiveClassesAtExit=dynamic-cds.jsa -cp <app jar> MyApp

这与上面的步骤 2 非常相似,但另外 -XX:SharedArchiveFile 选项用于指定 AppCDS 存档。

9.在同一命令行中链接动态 CDS 存档和 AppCDS 存档

还可以选择在同一命令行中链接 AppCDS 和动态 CDS 存档:

$ java -XX:SharedArchiveFile=static-cds.jsa:dynamic-cds.jsa -cp <app jar> MyApp

注意:Windows 上的分隔符是 ; (反斜杠分号)而不是:(冒号)

HotSpot 不支持两个以上的存档。

使用 -Xlog:cds 选项启动应用程序会打印两个存档:

$ java -Xlog:cds -XX:SharedArchiveFile=static-cds.jsa:dynamic-cds.jsa -cp <app jar> MyApp

[info][cds] trying to map static-cds.jsa
[info][cds] Opened archive static-cds.jsa.

[info][cds] trying to map dynamic-cds.jsa
[info][cds] Opened archive dynamic-cds.jsa.

10.使用 jcmd 创建应用程序/动态 CDS 存档

到目前为止,我们在前两节中已经看到,要创建 AppCDS 或动态 CDS 存档,需要增强应用程序启动脚本(使用其他 JVM 选项),并且需要多次重新启动应用程序。 在本节中,我将介绍一种使用 jcmd 工具创建静态存档和动态存档的简化方法。

首先,启动应用程序:

$ java -cp <app jar> MyApp

其次,在应用程序运行时使用 jcmd 转储档案:

$ jcmd <PID> VM.cds static_dump static-cds.jsa
$ jcmd <PID> VM.cds dynamic_dump dynamic-cds.jsa

注意:为了能够转储动态存档,与 对应的 JVM 进程需要在启动应用程序时(在第一步中)指定一个附加选项 - XX:+RecordDynamicDumpInfo。

11.不足和建议

使用与创建时不同的 JDK 版本运行 CDS 存档不起作用(即升级 JDK 版本而不重新生成存档)。 JDK 18、19(JDK-8272331、JDK-8261455)中已解决此问题。 例如,以下存档是使用 JDK 17 创建并使用 JDK 18 启动的。

$ java -Xlog:cds -XX:SharedArchiveFile=dynamic-cds.jsa -cp <app jar> MyApp

[info][cds] Opening shared archive: dynamic-cds.jsa
[info][cds] UseSharedSpaces: Cannot handle shared archive file version 11. Must be at least 12
[info][cds] Unable to use shared archive: invalid archive

CDS 存档不可跨平台重复使用(例如 Linux、Windows、macOS)。 例如,以下存档是在 Linux 上创建并在 Windows 上启动的(即使使用相同的 JDK 版本)。

$ java -Xlog:cds -XX:SharedArchiveFile=dynamic-cds.jsa -cp <app jar> MyApp

[info][cds] trying to map dynamic-cds.jsa
[info][cds] Opened archive dynamic-cds.jsa.
[info][cds] _jvm_ident expected: OpenJDK 64-Bit Server VM (17.0.2+8-86) for windows-amd64 JRE (17.0.2+8-86), built on Dec 7 2021 21:49:10 by "mach5one" with MS VC++ 16.8 / 16.9 (VS2019)
[info][cds] actual: OpenJDK 64-Bit Server VM (17.0.2+8-86) for linux-amd64 JRE (17.0.2+8-86), built on Dec 7 2021 21:41:21 by "mach5one" with gcc 10.3.0
[info][cds] UseSharedSpaces: The shared archive file was created by a different version or build of HotSpot
[info][cds] UseSharedSpaces: Unable to map shared spaces

生成存档后,在类路径或模块路径中使用修改后的 jar 时间戳运行 CDS 存档不起作用(即禁用动态存档,仅使用基础层存档)。 这意味着重新编译类并重新创建 jar(即使源 Java 类相同、相同的工件 id 和组 id)是不可能的。

$ java -Xlog:cds -XX:SharedArchiveFile=dynamic-cds.jsa -cp <app jar> MyApp

[info][cds] trying to map /usr/lib/jvm/openjdk-17.0.2/lib/server/classes.jsa
[info][cds] Opened archive /usr/lib/jvm/openjdk-17.0.2/lib/server/classes.jsa.
[info][cds] trying to map dynamic-cds.jsa
[info][cds] Opened archive dynamic-cds.jsa.
[info][cds] Reserved archive_space_rs [0x0000000800000000 - 0x0000000804400000] (71303168) bytes
[info][cds] Reserved class_space_rs   [0x0000000804400000 - 0x0000000844400000] (1073741824) bytes
[info][cds] Mapped static  region #0 at base 0x0000000800000000 top 0x0000000800457000 (ReadWrite)
[info][cds] Mapped static  region #1 at base 0x0000000800457000 top 0x0000000800bde000 (ReadOnly)
[info][cds] Mapped dynamic region #0 at base 0x0000000800bde000 top 0x00000008021aa000 (ReadWrite)
[info][cds] Mapped dynamic region #1 at base 0x00000008021aa000 top 0x0000000804130000 (ReadOnly)
[info][cds] UseSharedSpaces: A jar file is not the one used while building the shared archive file: target/my-app-0.0.1-SNAPSHOT.jar
[info][cds] Unmapping region #0 at base 0x0000000800bde000 (ReadWrite)
[info][cds] Unmapping region #1 at base 0x00000008021aa000 (ReadOnly)
[warning][cds,dynamic] Unable to use shared archive. The top archive failed to load: dynamic-cds.jsa

CDS 存档不包括 JDK 5/6 之前的类(JDK-8202556、JDK-8230413)。 例如,以下输出是在启用 -Xlog:cds 选项的情况下生成动态存档的结果。

$ java -Xlog:cds -XX:ArchiveClassesAtExit=dynamic-cds.jsa -cp <app jar> MyApp

[warning][cds] Pre JDK 6 class not supported by CDS: 49.0 jdk/internal/reflect/GeneratedConstructorAccessor30
[warning][cds] Pre JDK 6 class not supported by CDS: 49.0 org/springframework/cglib/core/internal/Function
[warning][cds] Pre JDK 6 class not supported by CDS: 49.0 net/bytebuddy/dynamic/scaffold/MethodRegistry$Compiled
[warning][cds] Pre JDK 6 class not supported by CDS: 46.0 antlr/collections/impl/ASTArray

如果指定了 --upgrade-module-path、–patch-module 或 --limit-modules 选项,则 CDS 将被禁用。

$ java -Xlog:cds -XX:SharedArchiveFile=dynamic-cds.jsa --upgrade-module-path=target/modules -cp <app jar> MyApp

[0.000s][info][cds] optimized module handling: disabled due to incompatible property: jdk.module.upgrade.path=target/modules

创建存档时使用的类路径必须与运行时使用的类路径相同(或其前缀)。 模块路径不遵循相同的限制。

应用程序/动态 CDS 不包括其他 jar 作为类路径属性引用的 jar。

动态 CDS 档案应该在更广泛地使用应用程序(涵盖应用程序中的不同业务流程)之后创建,而不是通过启动并立即停止应用程序(即延迟加载类)来创建。

JDK版本使用越新越好。 最新的 JDK 版本包括显着的 CDS 改进或错误修复,例如:

  • JDK 15 – 尝试在动态 CDS 转储期间链接所有类(即未链接)(JDK-8232081)
  • JDK 15 – 支持动态 CDS 存档中的 Lambda 代理类 (JDK-8198698)
  • JDK 15 – ZGC(生产就绪)支持 CDS(ZGC Main)
  • JDK 16 – 支持静态 CDS 存档中的 Lambda 代理类 (JDK-8247666)
  • JDK 17 – 将旧的类文件存储在静态 CDS 存档中 (JDK-8261090)

12.总结

在我看来,AppCDS 或动态 CDS 是您应该自己尝试的功能。 这是一种几乎可以免费带来好处的机制,您不必更改应用程序代码。 这些改进有多大,我无法告诉你,这取决于具体情况。

我最近在 Java 会议上提出了类似的主题(例如 CDS、AppCDS 和动态 CDS)。 您可以下载幻灯片,此外 GitHub 上还有一个简短的教程(包括一些命令行选项和我使用的应用程序)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622499.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【氮化镓】液态Ga在GaN(0001)和(0001̅)表面上的三维有序排列随温度的变化

文章标题是《Temperature dependence of liquid-gallium ordering on the surface of epitaxially grown GaN》&#xff0c;作者是Takuo Sasaki等人&#xff0c;发表在《Applied Physics Express》上。文章主要研究了在分子束外延(MBE)条件下&#xff0c;液态镓(Ga)在GaN(0001)…

探索在Apache SeaTunnel上使用Hudi连接器,高效管理大数据的技术

Apache Hudi是一个数据湖处理框架&#xff0c;通过提供简单的方式来进行数据的插入、更新和删除操作&#xff0c;Hudi能够帮助数据工程师和科学家更高效地处理大数据&#xff0c;并支持实时查询。 支持的处理引擎 Spark Flink SeaTunnel Zeta 主要特性 批处理 流处理 精确一次性…

状态模式和策略模式对比

状态模式和策略模式都是行为型设计模式&#xff0c;它们的主要目标都是将变化的行为封装起来&#xff0c;使得程序更加灵活和可维护。之所以将状态模式和策略模式进行比较&#xff0c;主要是因为两个设计模式的类图相似度较高。但是&#xff0c;从状态模式和策略模式的应用场景…

2024最新版JavaScript逆向爬虫教程-------基础篇之深入JavaScript运行原理以及内存管理

目录 一、JavaScript运行原理1.1 前端需要掌握的三大技术1.2 为什么要学习JavaScript1.3 浏览器的工作原理1.4 浏览器的内核1.5 浏览器渲染过程1.6 认识JavaScript引擎1.7 V8引擎以及JavaScript的执行过程1.8 V8引擎执行过程 二、JavaScript的执行过程2.1 初始化全局对象2.2 执…

解决宏定义后面无法加分号

总结&#xff1a;注意是针对单行if语句使用&#xff0c;并且宏定义后面必须带分号&#xff08;格式统一&#xff09; 参考连接 C语言种do_while(0)的妙用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1vk4y1R7VJ/?spm_id_from333.337.search-card.all.click&vd_…

Excel数据处理:动态数据分析报表、单元格数字格式、使用排序工具

1、在生成数据透视表之后选中一个单元格&#xff0c;点击插入&#xff0c;在图表中选择一个自己想要的图表。&#xff08;生成可视化的图表&#xff09; 2、在分析中找到切片器&#xff0c;通过点击切片器可以即时变换生成不同的可视化图&#xff0c;可以右键切片器选择关联两个…

matlab 对数坐标画图,及在曲线上加竖直线

matlab 对数坐标画图 方法一&#xff1a;直接对x、y值取对数&#xff0c;然后画图 plot(log(x), log(y), m, LineWidth,1, Marker,.);% ,Color,#EDB120 方法二&#xff1a;将x、y轴刻度改为对数形式 plot(x, y, r, LineWidth,1, Marker,); ax gca();% 获取当前坐标句柄 ax…

解决Oracle锁表的方法

在实际工作中&#xff0c;并发量比较大的项目&#xff0c;经常会出现锁表的问题&#xff0c;下面我将复现这个问题&#xff0c;并给出解决方法。 一、问题复现 1、session1修改aabb表的B字段为迪迦奥特曼&#xff0c;但是不提交该事务。 2、session2也修改这行的这个字段。 发…

【stomp实战】搭建一套websocket推送平台

前面几个小节我们已经学习了stomp协议&#xff0c;了解了stomp客户端的用法&#xff0c;并且搭建了一个小的后台demo&#xff0c;前端页面通过html页面与后端服务建立WebSocket连接。发送消息给后端服务。后端服务将消息内容原样送回。通过这个demo我们学习了前端stomp客户端的…

【leetcode面试经典150题】71. 对称二叉树(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

科技改变视听4K 120HZ高刷新率的投影、电视、电影终有用武之地

早在1888年&#xff0c;法国生理学家埃蒂安朱尔马莱就发明了一套盒式摄像机&#xff0c;能以120帧/s的速度在一条纸膜上曝光照片&#xff0c;但是当时没有相匹配的放映设备。而马莱的另一套拍摄设备是60帧/s的规格&#xff0c;并且图像质量非常好。 受此启发&#xff0c;雷诺的…

Linux上部署Jupyter notebook

安装jupyter notebook pip install notebook #或者 conda install notebook配置 jupyter notebook --generate-config## The IP address the notebook server will listen on. # Default: localhost # 设置可以访问的ip, 默认是localhost, 将其改为 * c.NotebookApp.ip *#…

AutoGPT-Forge使用教程,自行构建agent智能体

本博客给出AutoGPT-forge四个教程的翻译与理解&#xff0c;使用GPT4翻译&#xff0c; 参考官方教程https://aiedge.medium.com/autogpt-forge-a-comprehensive-guide-to-your-first-steps-a1dfdf46e3b4 使用AutoGPT Github代码日期2024/4/22&#xff1b; 博客开始编辑日期20…

java和python刷题的一些语法规则总结(未完成)

语法总结 Java篇1、代码补全2、编程题中常用头文件3、编程题常用的内置方法4、模版 Python篇1、2、编程题中常用的头文件3、编程题中常用的内置方法4、伪代码模版 去哪练习&#xff1f; 1、LeetCode上有个面试模拟 2、牛客公司真题&#xff08;ACM模式&#xff09; ⚠️ 笔试均…

Android Gradle查看依赖库

1.gradle :app:dependencies 输出列表展示了所有configuration下的依赖树&#xff0c;依赖关系明显&#xff0c;层次清晰。 2.日志太长可以写入本地文件gradle :app:dependencies > D:/log.txt 3.gradlew processReleaseManifest --stacktrace 跟踪具体报错文件 注…

解决Android studio更换sdk地址后flutter项目显示no device selected

问题描述 因为之前sdk的路径在c盘上,经常在更新或下在sdk后c盘饱满,于是就更换了sdk的路径,更换sdk路径后就导致flutter项目在选择设备的时候出现no device selected 找不到设备,但是在device Manager可以看到物理设备或者是虚拟设备。如下图所示。 问题分析 导致这个问题…

python 报错:ImportError: cannot import name ‘kaiser‘ from ‘scipy.signal‘

python 报错&#xff1a;ImportError: cannot import name kaiser from scipy.signal 介绍第一步&#xff1a;第二步&#xff1a;最终结果&#xff1a; 介绍 这个错误表明在导入 scipy.signal 模块时出现了问题&#xff0c;因为无法找到 kaiser 函数。可能的原因是 scipy 库没有…

C语言 | Leetcode C语言题解之第47题全排列II

题目&#xff1a; 题解&#xff1a; int* vis;void backtrack(int* nums, int numSize, int** ans, int* ansSize, int idx, int* perm) {if (idx numSize) {int* tmp malloc(sizeof(int) * numSize);memcpy(tmp, perm, sizeof(int) * numSize);ans[(*ansSize)] tmp;return…

什么样的汽车制造供应商管理平台 可以既高效又安全?

汽车制造供应商管理是汽车制造商最基础的工作项&#xff0c;因为在汽车制造环节&#xff0c;与供应商间存在着必不可少又高频的业务往来&#xff0c;而在汽车制造供应商之间&#xff0c;文件往来是确保业务顺利进行、沟通协作和质量控制的重要环节。这些文件往来涵盖了多个方面…

linux的“>”和“>>”

在Linux中&#xff0c;>和>>都是用于文件重定向的操作符&#xff0c;它们用于将命令的输出发送到文件中。 > 用于创建一个新文件或覆盖现有文件的内容。当你执行一个如 command > file.txt 的命令时&#xff0c;如果 file.txt 文件存在&#xff0c;它的内容将被…