【Android KOOM】KOOM Java层泄漏使用全解析

文章目录

  • 前言
  • 初始化OOMMonitor
  • make leak
  • 日志查看&堆快照输出
  • 源码分析篇

前言

要研究内存泄漏框架,KOOM是个不可忽略的优秀开源框架,由快手开源。这将是一个系列的文章。这篇文章作为开篇,来看看KOOM框架的demo是怎么制造Java层面的leak的。

下面通过官方给出的Demo代码作为入口,来分析和学习这个开源框架。

初始化OOMMonitor


OOMMonitorInitTask.INSTANCE.init(JavaLeakTestActivity.this.getApplication());OOMMonitor.INSTANCE.startLoop(true, false,5_000L);LeakMaker.makeLeak(this);

make leak

在适当的地方初始化OOMMonitor,然后人为制造泄漏。

下面看看内存泄漏的写法:

public abstract class LeakMaker<T> {List<T> uselessObjectList = new ArrayList<>();abstract void startLeak(Context context);private static List<LeakMaker> leakMakerList = new ArrayList<>();public static void makeLeak(Context context) {leakMakerList.add(new ActivityLeakMaker());leakMakerList.add(new BitmapLeakMaker());leakMakerList.add(new ByteArrayLeakMaker());leakMakerList.add(new FragmentLeakMaker());leakMakerList.add(new StringLeakMaker());for (LeakMaker leakMaker : leakMakerList) {leakMaker.startLeak(context);}for (int i = 0; i < 700; i++) {new Thread(() -> {try {Thread.sleep(200000);} catch (InterruptedException e) {e.printStackTrace();}}).start();}}
}

新建了一个容器,把各种leak maker放进去,然后startLeak,接着开启大量的子线程。
需要注意的是startLeak写成了抽象方法,看下实现类:

public class ActivityLeakMaker extends LeakMaker<Activity> {@Overridepublic void startLeak(Context context) {LeakedActivity.setUselessObjectList(uselessObjectList);Intent intent = new Intent(context, LeakedActivity.class);context.startActivity(intent);}public static class LeakedActivity extends AppCompatActivity {static List<Activity> uselessObjectList;public static void setUselessObjectList(List<Activity> activities) {uselessObjectList = activities;}@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);uselessObjectList.add(this);this.finish();}}}

会跳转到LeakedActivity,其中LeakedActivity里面会持有一个静态的成员变量uselessObjectList,在LeakedActivity创建好的时候把它传进去,这样一来,静态变量持有activity,便会在activity被销毁的时候发生内存泄漏,LeakedActivity被静态变量持有,无法被释放。

再看看另外一个leak maker:

public class BitmapLeakMaker extends LeakMaker<Bitmap> {@Overridepublic void startLeak(Context context) {Bitmap bitmap = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);uselessObjectList.add(bitmap);}
}

新建一张bitmap,然后添加到容器。

public class ByteArrayLeakMaker extends LeakMaker<ByteArrayLeakMaker.ByteArrayHolder> {@Overridepublic void startLeak(Context context) {uselessObjectList.add(new ByteArrayHolder());}public static class ByteArrayHolder {private byte[] array;public ByteArrayHolder() {array = new byte[512 * 1024];}}}

这次是byte数组。

public class StringLeakMaker extends LeakMaker<String> {@Overridevoid startLeak(Context context) {String largeStr = new String(new byte[512 * 1024]);uselessObjectList.add(largeStr);}
}

这次是String,其它的也都大同小异。都是新建对象,然后添加抽象父类的容器里面,目的就是添加不同类的大对象到堆内存里面。便于后续测试框架检测leak的功能。

还有个需要注意的地方,这个地方很重要。LeakMaker抽象类里面的leakMakerList,这是个静态变量,把各个子类对象添加到leakMakerList,由于它是静态的,所以可以作为GCRoot。又因为它持有了这些子类LeakMaker对象,所以会导致这些子类LeakMaker对象无法被释放,造成内存泄漏。

各个leakMaker执行startLeak之后,开启大量的子线程,然后让子线程进行睡眠。

日志查看&堆快照输出

接着可以看到一些框架打印的log:


2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_SystemInfo: ----OOM Monitor Memory----
2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_SystemInfo: [java] max:402653184 used ratio:1%
2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_SystemInfo: [proc] VmSize:2269420kB VmRss:94936kB Threads:718
2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_SystemInfo: [meminfo] MemTotal:1548704kB MemFree:308960kB MemAvailable:973536kB
2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_SystemInfo: avaliable ratio:62% CmaTotal:0kB ION_heap:0kB
2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_ThreadOOMTracker: [meet condition] overThresholdCount:1, threadCount: 718
2024-03-08 16:46:52.102 5647-5687/com.kwai.koom.demo I/OOMMonitor_ThreadOOMTracker: over threshold dumpThreadIfNeed
2024-03-08 16:46:52.425 5647-5652/com.kwai.koom.demo I/zygote: Do partial code cache collection, code=123KB, data=57KB
2024-03-08 16:46:52.428 5647-5652/com.kwai.koom.demo I/zygote: After code cache collection, code=123KB, data=57KB
2024-03-08 16:46:52.428 5647-5652/com.kwai.koom.demo I/zygote: Increasing code cache capacity to 512KB
2024-03-08 16:46:52.524 5647-5687/com.kwai.koom.demo I/OOMMonitor_ThreadOOMTracker: threadNames = [.kwai.koom.demo, Jit thread pool, Signal Catcher, JDWP, ReferenceQueueD, FinalizerDaemon, FinalizerWatchd, HeapTaskDaemon, Binder:5647_1, Binder:5647_2, Profile Saver, RenderThread, RenderThread, hwuiTask1, hwuiTask2, Binder:5647_3, queued-work-loo, LoopThread, Thread-2, Thread-3, Thread-4, Thread-5, Thread-6, Thread-7, Thread-8, Thread-9, Thread-10, Thread-11, Thread-12, Thread-13, Thread-14, Thread-15, Thread-16, Thread-17, Thread-18, Thread-19, Thread-20, Thread-21, Thread-22, Thread-23, Thread-24, Thread-25, Thread-26, Thread-27, Thread-28, Thread-29, Thread-30, Thread-31, Thread-32, Thread-33, Thread-34, Thread-35, Thread-36, Thread-37, Thread-38, Thread-39, Thread-40, Thread-41, Thread-42, Thread-43, Thread-44, Thread-45, Thread-46, Thread-47, Thread-48, Thread-49, Thread-50, Thread-51, Thread-52, Thread-53, Thread-54, Thread-55, Thread-56, Thread-57, Thread-58, Thread-59, Thread-60, Thread-61, Thread-62, Thread-63, Thread-64, Thread-65, Thread-66, Thread-67, Thread-68, Thread-69, Thread-70, Thread-71, Thread-72, Thread-73, Thread-74, Thread-75, Thread-76, Thread-77, Thread-78, Thread-79, Thread-80, Thread-81, Thread-82, Thread-83, Thread-84, Thread-85, Thread-86, Thread-87, Thread-88, Thread-89, Thread-90, Thread-91, Thread-92, Thread-93, Thread-94, Thread-95, Thread-96, Thread-97, Thread-98, Thread-99, Thread-100, Thread-101, Thread-102, Thread-103, Thread-104, Thread-105, Thread-106, Thread-107, Thread-108, Thread-109, Thread-110, Thread-111, Thread-112, Thread-113, Thread-114, Thread-115, Thread-116, Thread-117, Thread-118, Thread-119, Thread-120, Thread-121, Thread-122, Thread-123, Thread-124, Thread-125, Thread-126, Thread-127, Thread-128, Thread-129, Thread-130, Thread-131, Thread-132, Thread-133, Thread-134, Thread-135, Thread-136, Thread-137, Thread-138, Thread-139, Thread-140, Thread-141, Thread-142, Thread-143, Thread-144, Thread-145, Thread-146, Thread-147, Thread-148, Thread-149, Thread-150, Thread-151, Thread-152, Thread-153, Thread-154, Thread-155, Thread-156, Thread-157, Thread-158, Thread-159, Thread-160, Thread-161, Thread-162, Thread-163, Thread-164, Thread-165, Thread-166, Thread-167, Thread-168, Thread-169, Thread-170, Thread-171, Thread-172, Thread-173, Thread-174, Thread-175, Thread-176, Thread-177, Thread-178, Thread-179, Thread-180, Thread-181, Thread-182, Thread-183, Thread-184, Thread-185, Thread-186, Thread-187, Thread-188, Thread-189, Thread-190, Thread-191, Thread-192, Thread-193, Thread-194, Thread-195, Thread-196, Thread-197, Thread-198, Thread-199, Thread-200, Thread-201, Thread-202, Thread-203, Thread-204, Thread-205, Thread-206, Thread-207, Thread-208, Thread-209, Thread-210, Thread-211, Thread-212, Thread-213, Thread-214, Thread-215, Thread-216, Thread-217, Thread-218, Thread-219, Thread-220, Thread-221, Thread-222, Thread-223, Thread-224, Thread-225, Thread-226, Thread-227, Thread-228, Thread-229, Thread-230, Thread-231, Thread-232, Thread-233, Thread-234, Thread-235, Thread-236, Thread-237, Thread-238, Thread-239, Thread-240, Thread-241, Thread-242, Thread-243, Thread-244, Thread-245, Thread-246, Thread-247, Thread-248, Thread-249, Thread-250, Thread-251, Thread-252, Thread-253, Thread-254, Thread-255, Thread-256, Thread-257, Thread-258, Thread-259, Thread-260, Thread-261, Thread-262, Thread-263, Thread-264, Thread-265, Thread-266, Thread-267, Thread-268, Thread-269, Thread-270, Thread-271, Thread-272, Thread-273, Thread-274, Thread-275, Thread-276, Thread-277, Thread-278, Thread-279, Thread-280, Thread-281, Thread-282, Thread-283, Thread-284, Thread-285, Thread-286, Thread-287, Thread-288, Thread-289, Thread-290, Thread-291, Thread-292, Thread-293, Thread-294, Thread-295, Thread-296, Thread-297, Thread-298, Thread-299, Thread-300, Thread-301, Thread-302, Thread-303, Thread-304, Thread-305, Thread-306, Thread-307, Thread-308, Thread-309, Thread-310, Thread-311, Thread-312, Thread-313, Thread-314, Thread-315, Thread-316, Thread-317, Thread-318, Thread-319, Thread-320, Thread-321, Thread-322, Thread-323, Thr
2024-03-08 16:46:52.532 5647-5687/com.kwai.koom.demo I/OOMMonitor: OOMPreferenceManager.getFirstAnalysisTime():1709884924454
2024-03-08 16:46:52.532 5647-5687/com.kwai.koom.demo I/OOMMonitor: OOMPreferenceManager.getAnalysisTimes:3
2024-03-08 16:46:52.533 5647-6389/com.kwai.koom.demo I/OOMMonitor: mTrackReasons:[reason_thread_oom]
2024-03-08 16:46:52.533 5647-6389/com.kwai.koom.demo I/OOMMonitor: dumpAndAnalysis
2024-03-08 16:46:52.535 5647-6390/com.kwai.koom.demo I/OOMMonitor: processHprofFile
2024-03-08 16:46:52.536 5647-6390/com.kwai.koom.demo I/OOMMonitor: delete other version files thread
2024-03-08 16:46:52.538 5647-6390/com.kwai.koom.demo I/OOMMonitor: delete old files
2024-03-08 16:46:52.542 5647-6390/com.kwai.koom.demo I/OOMMonitor: create json file and then start service
2024-03-08 16:46:52.545 5647-6390/com.kwai.koom.demo I/OOMMonitor_HeapAnalysisService: startAnalysisService
2024-03-08 16:46:52.549 5647-6390/com.kwai.koom.demo E/memtrack: Couldn't load memtrack module
2024-03-08 16:46:52.549 5647-6390/com.kwai.koom.demo W/android.os.Debug: failed to get memory consumption info: -1
2024-03-08 16:46:52.550 5647-6389/com.kwai.koom.demo I/OOMMonitor: hprof analysis dir:/storage/emulated/0/Android/data/com.kwai.koom.demo/files/performance/oom/memory/hprof-aly
2024-03-08 16:46:52.550 5647-6389/com.kwai.koom.demo I/OOMMonitor_ForkJvmHeapDumper: dump /storage/emulated/0/Android/data/com.kwai.koom.demo/files/performance/oom/memory/hprof-aly/1.0.0_2024-03-08_16-46-52_535.hprof
2024-03-08 16:46:52.589 5647-6389/com.kwai.koom.demo V/kwai_dlfcn: android_api_ = 26
2024-03-08 16:46:52.653 5647-6389/com.kwai.koom.demo I/OOMMonitor_ForkJvmHeapDumper: before suspend and fork.
2024-03-08 16:46:52.766 5647-6390/com.kwai.koom.demo I/OOMMonitor_HeapAnalysisService: startAnalysisService get Pss:28731
2024-03-08 16:46:52.790 5647-6390/com.kwai.koom.demo I/OOMMonitor: delete other version files fd
2024-03-08 16:46:53.399 5647-6389/com.kwai.koom.demo I/OOMMonitor_ForkJvmHeapDumper: dump true, notify from pid 6391
2024-03-08 16:46:53.399 5647-6389/com.kwai.koom.demo I/OOMMonitor: end hprof dump
2024-03-08 16:46:54.400 5647-6389/com.kwai.koom.demo I/OOMMonitor: start hprof analysis
2024-03-08 16:46:54.401 5647-6389/com.kwai.koom.demo I/OOMMonitor_HeapAnalysisService: startAnalysisService
2024-03-08 16:46:54.401 5647-6389/com.kwai.koom.demo E/memtrack: Couldn't load memtrack module
2024-03-08 16:46:54.402 5647-6389/com.kwai.koom.demo W/android.os.Debug: failed to get memory consumption info: -1
2024-03-08 16:46:54.516 5647-6389/com.kwai.koom.demo I/OOMMonitor_HeapAnalysisService: startAnalysisService get Pss:39764
2024-03-08 16:46:55.207 5647-5660/com.kwai.koom.demo I/OOMMonitor: heap analysis success, do upload
2024-03-08 16:46:55.207 5647-5660/com.kwai.koom.demo I/OOMMonitor: {"classInfos":[{"className":"libcore.util.NativeAllocationRegistry$CleanerThunk","instanceCount":"969"},{"className":"androidx.lifecycle.ReportFragment","instanceCount":"1"},{"className":"com.android.internal.policy.PhoneWindow","instanceCount":"3"},{"className":"com.kwai.koom.demo.javaleak.test.ActivityLeakMaker$LeakedActivity","instanceCount":"1"},{"className":"libcore.util.NativeAllocationRegistry","instanceCount":"114"},{"className":"android.graphics.Bitmap","instanceCount":"1"}],"gcPaths":[{"gcRoot":"System class","instanceCount":1,"leakReason":"Activity Leak","path":[{"declaredClass":"com.kwai.koom.demo.javaleak.test.ActivityLeakMaker$LeakedActivity","reference":"com.kwai.koom.demo.javaleak.test.ActivityLeakMaker$LeakedActivity.uselessObjectList","referenceType":"STATIC_FIELD"},{"declaredClass":"java.util.ArrayList","reference":"java.util.ArrayList.elementData","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.lang.Object[]","reference":"java.lang.Object[]","referenceType":"ARRAY_ENTRY"},{"reference":"com.kwai.koom.demo.javaleak.test.ActivityLeakMaker$LeakedActivity","referenceType":"instance"}],"signature":"39a5e85640a0de9a3a4d9caf88798ce8321a30"},{"gcRoot":"System class","instanceCount":1,"leakReason":"Bitmap Size Over Threshold, 1920x1080","path":[{"declaredClass":"com.kwai.koom.demo.javaleak.test.LeakMaker","reference":"com.kwai.koom.demo.javaleak.test.LeakMaker.leakMakerList","referenceType":"STATIC_FIELD"},{"declaredClass":"java.util.ArrayList","reference":"java.util.ArrayList.elementData","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.lang.Object[]","reference":"java.lang.Object[]","referenceType":"ARRAY_ENTRY"},{"declaredClass":"com.kwai.koom.demo.javaleak.test.LeakMaker","reference":"com.kwai.koom.demo.javaleak.test.BitmapLeakMaker.uselessObjectList","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.util.ArrayList","reference":"java.util.ArrayList.elementData","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.lang.Object[]","reference":"java.lang.Object[]","referenceType":"ARRAY_ENTRY"},{"reference":"android.graphics.Bitmap","referenceType":"instance"}],"signature":"a2f199eabc1292bcb4f813615818e5383a4988c8"},{"gcRoot":"System class","instanceCount":1,"leakReason":"Primitive Array Size Over Threshold, 524301","path":[{"declaredClass":"com.kwai.koom.demo.javaleak.test.LeakMaker","reference":"com.kwai.koom.demo.javaleak.test.LeakMaker.leakMakerList","referenceType":"STATIC_FIELD"},{"declaredClass":"java.util.ArrayList","reference":"java.util.ArrayList.elementData","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.lang.Object[]","reference":"java.lang.Object[]","referenceType":"ARRAY_ENTRY"},{"declaredClass":"com.kwai.koom.demo.javaleak.test.LeakMaker","reference":"com.kwai.koom.demo.javaleak.test.ByteArrayLeakMaker.uselessObjectList","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.util.ArrayList","reference":"java.util.ArrayList.elementData","referenceType":"INSTANCE_FIELD"},{"declaredClass":"java.lang.Object[]","reference":"java.lang.Object[]","referenceType":"ARRAY_ENTRY"},{"declaredClass":"com.kwai.koom.demo.javaleak.test.ByteArrayLeakMaker$ByteArrayHolder","reference":"com.kwai.koom.demo.javaleak.test.ByteArrayLeakMaker$ByteArrayHolder.array","referenceType":"INSTANCE_FIELD"},{"reference":"byte[]","referenceType":"array"}],"signature":"6d4e5ac7bf79b44c133b56b02a3b4ec1dd4aab"}],"leakObjects":[{"className":"android.graphics.Bitmap","extDetail":"1920 x 1080","objectId":"318378712","size":"2073600"},{"className":"char[]","objectId":"2394423312","size":"1048589"},{"className":"byte[]","objectId":"2397057024","size":"524301"}],"runningInfo":{"buildModel":"Android SDK built for x86","currentPage":"javaleak.JavaLeakTestActivity","deviceMemAvaliable":"950.71875","deviceMemTotal":"1512.4062","dumpReason":"reanalysis","fdCount":"56","filterInstanceTime":"0.424","findGCPathTime":"1.188","jvmMax":"384.0","jvmUsed":"4.2463074","manufacture":"Google","nowTime":"2024-03-08_16-46-52_774","pss":"28.057617mb","rss":"92.71094mb","sdkInt":
2024-03-08 16:46:55.208 5647-5660/com.kwai.koom.demo E/OOMMonitor: todo, upload report 1.0.0_2024-03-08_16-34-51_816.json if necessary
2024-03-08 16:46:55.208 5647-5660/com.kwai.koom.demo E/OOMMonitor: todo, upload hprof 1.0.0_2024-03-08_16-34-51_816.hprof if necessary
2024-03-08 16:50:07.178 5647-5710/com.kwai.koom.demo W/zygote: No such thread id for suspend: 86

从日志可以看出来,进行一轮heap分析之后,会在日志给出整体的数据。还会保存一份json格式和hprof格式的heap快照,开发者可以选择上传到自己的服务器上。

仔细观察还能发现一个细节,OOMMonitor_ForkJvmHeapDumper: before suspend and fork,也就是说,KOOM会挂起并fork当前进程。这样做的原因,大概是为了不要在GC STW的时候卡住APP。这也是和leakcanary框架不一样的地方。

本次代码导出的hprof文件已经通过hprof-conv命令进行转换,可以直接用MAT内存分析工具打开,文件已经上传。大家可以在文章头下载研究和学习。

至于更加深入的内容,这段时间会尽快在后续的文章会进一步分析和总结,同样在研究和学习性能相关的内容的朋友可以持续关注。

源码分析篇

这一篇会剖析KOOM的源码设计逻辑,已更新到下面链接:

【Android 内存优化】KOOM Java Leak 源码剖析

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

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

相关文章

C++的类与对象(三):构造函数、析构函数、对象的销毁顺序

目录 类的6个默认成员函数 构造函数 语法 特性 析构函数 特性 对象的销毁顺序​​​​​​​​​​​​​​ 类的6个默认成员函数 问题&#xff1a;一个什么成员都没的类叫做空类&#xff0c;空类中真的什么都没有吗&#xff1f; 基本概念&#xff1a;任何类在什么都不…

软考73-上午题-【面向对象技术2-UML】-UML中的图4

一、构件图&#xff08;组件图&#xff09; 1-1、构件图的定义 展现了&#xff0c;一组构件之间的组织和依赖。 构件图专注于系统的静态实现图。 构件图与类图相关&#xff0c;通常把构件映射为一个、多个类、接口、协作。 【回顾】&#xff1a; 类图展示了一组对象、接口、…

题目 2146: 组合的输出

题目描述: 排列与组合是常用的数学方法&#xff0c;其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n)&#xff0c;我们可以简单地将n个元素理解为自然数1&#xff0c;2&#xff0c;…&#xff0c;n&#xff0c;从中任取r个数。 现要求你用递归的方法输出所有组合。 例如n&…

SpringCloud-SpringBoot读取Nacos上的配置文件

在 Spring Boot 应用程序中&#xff0c;可以使用 Spring Cloud Nacos 来实现从 Nacos 服务注册中心和配置中心读取配置信息。以下是如何在 Spring Boot 中读取 Nacos 上的配置文件的步骤&#xff1a; 1. 引入依赖 首先&#xff0c;在 Spring Boot 项目的 pom.xml 文件中添加 …

深入探索Java设计模式:责任链模式解析与实践

目录 一、责任链模式的基础知识1. 模式结构2. 模式示例 二、责任链模式的实际应用1. 请求处理链2. 日志记录器 三、责任链模式的重要性和使用场景结语 欢迎阅读本篇博客&#xff0c;我们将深入探讨Java设计模式中的责任链模式&#xff0c;帮助初学者、初中级程序员和在校大学生…

Android Kotlin知识汇总(一)编程语言

在 2019 年 Google I/O 大会上宣布今后将优先采用 Kotlin 进行 Android 开发。Kotlin 是一种富有表现力且简洁的编程语言&#xff0c;不仅可以减少常见代码错误&#xff0c;还可以轻松集成到现有应用中。如果您想构建 Android 应用&#xff0c;建议您从 Kotlin 开始着手&#x…

分享axios+signalr简单封装示例

Ajax Axios Axios 是一个基于 promise 网络请求库&#xff0c;作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。 从浏览器创建 XMLHttpReque…

MySQL-QA-异常问题及解决方案(持续更新)

MySQL-Q&A(持续更新) 1.1 PID文件找不到 问题描述 错误详情&#xff1a; ERROR&#xff01;The server quit without updating PID file (/usr/local/mysql/data/localhost.localdomain.pid) 解决方案 首先排查配置文件&#xff0c;一般路径为&#xff1a;/etc/my.cnf 检查…

Python 利用Pydantic模块提升开发效率

文章目录 Pydantic 核心概念pydantic 核心功能BaseModel 模型Field 类Config 类基础类型验证必填字段验证长度验证大小验证枚举值验证容器验证自定义验证器嵌套模型JSON 数据导入ORM 数据导入总结 Pydantic 核心概念 Pydantic 是一个数据验证和设置管理库&#xff0c;它的核心概…

D2力扣滑动窗口系列

滑动窗口算法&#xff08;Sliding Window&#xff09;&#xff1a; 滑动窗口算法&#xff08;Sliding Window&#xff09;&#xff1a;在给定数组 / 字符串上维护一个固定长度或不定长度的窗口。可以对窗口进行滑动操作、缩放操作&#xff0c;以及维护最优解操作。 滑动操作&am…

【Ubuntu】gonme桌面的 gdm 和 lightdm 区别

总结&#xff1a;都可以 gdm: 【Gnome Display Manager】 完整&#xff0c;体积大 lightdm: 【Light Display Manager】 轻量

甜甜圈和贪吃蛇的后续

代码复现-项目复现 代码复现 云课五分钟-02第一个代码复现-终端甜甜圈C-CSDN博客 项目复现 云课五分钟-03第一个开源游戏复现-贪吃蛇-CSDN博客 不同的地图 加入班级和标识 循序渐进 这些案例都是来源网络&#xff0c;只是方便熟悉一下云课使用过程。 此部分学生掌握情况非…

OpenCV 图像的几何变换

一、图像缩放 1.API cv2.resize(src, dsize, fx0,fy0,interpolation cv2.INTER_LINEAR) 参数&#xff1a; ①src &#xff1a;输入图像 ②dsize&#xff1a;绝对尺寸 ③fx&#xff0c;fy&#xff1a;相对尺寸 ④interpolation&#xff1a;插值方法 2.代码演示 import cv2 …

携手亚信安慧AntDB,在数智化浪潮中乘风破浪

随着大数据时代的到来&#xff0c;对数据库的需求愈发强烈。在这一背景下&#xff0c;国产数据库逐渐崭露头角&#xff0c;亚信安慧AntDB作为重要的代表产品之一正积极参与到激烈的市场竞争中。亚信安慧AntDB不仅追求技术的革新和突破&#xff0c;同时也致力于满足用户日益增长…

AVCE - AV Evasion Craft Online 更新 8 种加载方式 - 过 WD 等

免责声明&#xff1a;本工具仅供安全研究和教学目的使用&#xff0c;用户须自行承担因使用该工具而引起的一切法律及相关责任。作者概不对任何法律责任承担责任&#xff0c;且保留随时中止、修改或终止本工具的权利。使用者应当遵循当地法律法规&#xff0c;并理解并同意本声明…

2023年中国高校大数据挑战赛D题参考论文发布(全网首发)

腾讯文档】2023年大数据挑战赛资料说明 https://docs.qq.com/doc/DSEpWUVFySm1ObFB0 基于数据分析的行业职业技术培训能力评价 摘要 中国是制造业大国&#xff0c;产业门类齐全&#xff0c;每年需要培养大量的技能娴熟的技术工人进入工厂。本文将基于题目给出的数据&#x…

VuePress使用

1、创建项目 参考官网创建 参考文章

Java——正则表达式详解

目录 Java正则表达式1、正则表达式语法1.1、基本的元字符1.2、数量元字符1.3、位置元字符1.4、特殊字符元字符1.5、回溯引用和前后查找1.6、大小写转换1.7、匹配模式 2、Java中的正则表达式2.1、概述2.2、获取匹配位置2.3、捕获组 3、匹配单个字符3.1、匹配纯文本3.2、匹配任意…

讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so

1.需求 最近linux下的Qt项目中要连接oracle数据库&#xff0c;用户需要我们访问他们的oracle数据库&#xff0c;查询数据 2.遇到的问题 qt连接oracle数据库需要oracle的驱动库libqsqloci.so插件&#xff0c;需要编译下&#xff0c;之前没有编译过&#xff0c;看了网上的…

蓝桥杯真题讲解:异或和之和 (拆位、贡献法)

蓝桥杯真题讲解&#xff1a;异或和之和 &#xff08;拆位、贡献法&#xff09; 一、视频讲解二、正解代码 一、视频讲解 蓝桥杯真题讲解&#xff1a;异或和之和 &#xff08;拆位、贡献法&#xff09; 二、正解代码 //拆位考虑 #include<bits/stdc.h> #define endl &…