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

Android ANR 总结

工作之余,对之前学习到的和结合自己项目过程中的遇到的问题经验做一些总结,下面讲一讲Android开发过程中遇到的ANR的问题,做一下整理

一、概述

解决ANR一直是Android 开发者需要掌握的重要技巧,一般从三个方面着手。

开发阶段:通过工具检查各个方法的耗时,卡顿情况,发现一处修改一处。

线上阶段:这个阶段主要依靠监控工具发现ANR并上报,比如matrix。

分析阶段:如果线上用户发生ANR,并且你获取了一份日志,这就涉及了本文要分享的内容——ANR日志分析技巧

二、ANR产生机制

ANR——应用无响应,Activity是5秒,BroadCastReceiver是10秒,Service是20秒。

这句话说的很笼统,要想深入分析定位ANR,需要知道更多知识点,一般来说,ANR按产生机制,分为4类:

①输入事件超时(5s)

②广播类型超时(前台15s,后台60s)

③服务超时(前台20s,后台200s)

④ContentProvider 类型

2.1 输入事件超时(5s)

InputEvent Timeout

  1. a.InputDispatcher发送key事件给 对应的进程的 Focused Window ,对应的window不存在、处于暂停态、或通道(input channel)占满、通道未注册、通道异常、或5s内没有处理完一个事件,就会发生ANR
  2. b.InputDispatcher发送MotionEvent事件有个例外之处:当对应Touched Window的 input waitQueue中有超过0.5s的事件,inputDispatcher会暂停该事件,并等待5s,如果仍旧没有收到window的‘finish’事件,则触发ANR
  3. c.下一个事件到达,发现有一个超时事件才会触发ANR

 2.2 广播类型超时(前台15s,后台60s)

BroadcastReceiver Timeout

  1. a.静态注册的广播和有序广播会ANR,动态注册的非有序广播并不会ANR
  2. b.广播发送时,会判断该进程是否存在,不存在则创建,创建进程的耗时也算在超时时间里
  3. c.只有当进程存在前台显示的Activity才会弹出ANR对话框,否则会直接杀掉当前进程
  4. d.当onReceive执行超过阈值(前台15s,后台60s),将产生ANR
  5. e.如何发送前台广播:Intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)

2.3 服务超时(前台20s,后台200s)

Service Timeout

  1. a.Service的以下方法都会触发ANR:onCreate(),onStartCommand(), onStart(), onBind(), onRebind(), onTaskRemoved(), onUnbind(),onDestroy().
  2. b.前台Service超时时间为20s,后台Service超时时间为200s
  3. c.如何区分前台、后台执行————当前APP处于用户态,此时执行的Service则为前台执行。
  4. d.用户态:有前台activity、有前台广播在执行、有foreground service执行

2.4 ContentProvider 类型

  1. a.ContentProvider创建发布超时并不会ANR
  2. b.使用ContentProviderclient来访问ContentProverder可以自主选择触发ANR,超时时间自己定
  3. client.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);

三、导致ANR的原因

很多开发者认为,那就是耗时操作导致ANR,全部是app应用层的问题。实际上,线上环境大部分ANR由系统原因导致。

①应用层导致ANR(耗时操作)

② 系统导致ANR

3.1 应用层导致ANR(耗时操作)

  1. a. 函数阻塞:如死循环、主线程IO、处理大数据
  2. b. 锁出错:主线程等待子线程的锁
  3. c. 内存紧张:系统分配给一个应用的内存是有上限的,长期处于内存紧张,会导致频繁内存交换,进而导致应用的一些操作超时

3.2 系统导致ANR

  1. a. CPU被抢占:一般来说,前台在玩游戏,可能会导致你的后台广播被抢占CPU
  2. b. 系统服务无法及时响应:比如获取系统联系人等,系统的服务都是Binder机制,服务能力也是有限的,有可能系统服务长时间不响应导致ANR
  3. c. 其他应用占用的大量内存 

四、分析日志

发生ANR的时候,系统会产生一份anr日志文件(手机的/data/anr 目录下,文件名称可能各厂商不一样,业内大多称呼为trace文件),内含如下几项重要信息。

① CPU 负载

②内存信息

③ 堆栈消息

4.1 CPU 负载

  1. Load: 2.62 / 2.55 / 2.25
  2. CPU usage from 0ms to 1987ms later (2020-03-10 08:31:55.169 to 2020-03-10 08:32:17.156):
  3.   41% 2080/system_server: 28% user + 12% kernel / faults: 76445 minor 180 major
  4.   26% 9378/com.xiaomi.store: 20% user + 6.8% kernel / faults: 68408 minor 68 major
  5. ........省略N行.....
  6. 66% TOTAL: 20% user + 15% kernel + 28% iowait + 0.7% irq + 0.7% softirq

如上所示:

  • 第一行:1、5、15 分钟内正在使用和等待使用CPU 的活动进程的平均数
  • 第二行:表明负载信息抓取在ANR发生之后的0~1987ms。同时也指明了ANR的时间点:2020-03-10 08:31:55.169
  • 中间部分:各个进程占用的CPU的详细情况
  • 最后一行:各个进程合计占用的CPU信息。

名词解释:

  1. a. user:用户态,kernel:内核态
  2. b. faults:内存缺页,minor——轻微的,major——重度,需要从磁盘拿数据
  3. c. iowait:IO使用(等待)占比
  4. d. irq:硬中断,softirq:软中断

注意:
iowait占比很高,意味着有很大可能,是io耗时导致ANR,具体进一步查看有没有进程faults major比较多。

  • 单进程CPU的负载并不是以100%为上限,而是有几个核,就有百分之几百,如4核上限为400%。

 4.2 内存信息

  1. Total number of allocations 476778  进程创建到现在一共创建了多少对象
  2. Total bytes allocated 52MB 进程创建到现在一共申请了多少内存
  3. Total bytes freed 52MB   进程创建到现在一共释放了多少内存
  4. Free memory 777KB    不扩展堆的情况下可用的内存
  5. Free memory until GC 777KB  GC前的可用内存
  6. Free memory until OOME 383MB  OOM之前的可用内存
  7. Total memory 当前总内存(已用+可用)
  8. Max memory 384MB 进程最多能申请的内存

从含义可以得出结论:Free memory until OOME 的值很小的时候,已经处于内存紧张状态。应用可能是占用了过多内存。

ps:如果ANR时间点前后,日志里有打印onTrimMemory,也可以作为内存紧张的一个参考判断

4.3 堆栈消息

堆栈信息是最重要的一个信息,展示了ANR发生的进程当前所有线程的状态。

  1. suspend all histogram: Sum: 2.834s 99% C.I. 5.738us-7145.919us Avg: 607.155us Max: 41543us
  2. DALVIK THREADS (248):
  3. "main" prio=5 tid=1 Native
  4.   | group="main" sCount=1 dsCount=0 flags=1 obj=0x74b17080 self=0x7bb7a14c00
  5.   | sysTid=2080 nice=-2 cgrp=default sched=0/0 handle=0x7c3e82b548
  6.   | state=S schedstat=( 757205342094 583547320723 2145008 ) utm=52002 stm=23718 core=5 HZ=100
  7.   | stack=0x7fdc995000-0x7fdc997000 stackSize=8MB
  8.   | held mutexes=
  9.   kernel: __switch_to+0xb0/0xbc
  10.   kernel: SyS_epoll_wait+0x288/0x364
  11.   kernel: SyS_epoll_pwait+0xb0/0x124
  12.   kernel: cpu_switch_to+0x38c/0x2258
  13.   native: #00 pc 000000000007cd8c /system/lib64/libc.so (__epoll_pwait+8)
  14.   native: #01 pc 0000000000014d48 /system/lib64/libutils.so (android::Looper::pollInner(int)+148)
  15.   native: #02 pc 0000000000014c18 /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+60)
  16.   native: #03 pc 0000000000127474 /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
  17.   at android.os.MessageQueue.nativePollOnce(Native method)
  18.   at android.os.MessageQueue.next(MessageQueue.java:330)
  19.   at android.os.Looper.loop(Looper.java:169)
  20.   at com.android.server.SystemServer.run(SystemServer.java:508)
  21.   at com.android.server.SystemServer.main(SystemServer.java:340)
  22.   at java.lang.reflect.Method.invoke(Native method)
  23.   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:536)
  24.   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:856
  25.   ........省略N行....
  26.   "OkHttp ConnectionPool" daemon prio=5 tid=251 TimedWaiting
  27.   | group="main" sCount=1 dsCount=0 flags=1 obj=0x13daea90 self=0x7bad32b400
  28.   | sysTid=29998 nice=0 cgrp=default sched=0/0 handle=0x7b7d2614f0
  29.   | state=S schedstat=( 951407 137448 11 ) utm=0 stm=0 core=3 HZ=100
  30.   | stack=0x7b7d15e000-0x7b7d160000 stackSize=1041KB
  31.   | held mutexes=
  32.   at java.lang.Object.wait(Native method)
  33.   - waiting on <0x05e5732e> (a com.android.okhttp.ConnectionPool)
  34.   at com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:103)
  35.   - locked <0x05e5732e> (a com.android.okhttp.ConnectionPool)
  36.   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  37.   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  38.   at java.lang.Thread.run(Thread.java:764)

如上日志所示,本文截图了两个线程信息,一个是主线程main,它的状态是native。

另一个是OkHttp ConnectionPool,它的状态是TimeWaiting。众所周知,教科书上说线程状态有5种:新建、就绪、执行、阻塞、死亡。而Java中的线程状态有6种,6种状态都定义在:java.lang.Thread.State中

问题来了,上述main线程的native是什么状态,哪来的?其实trace文件中的状态是是CPP代码中定义的状态

由此可知,main函数的native状态是正在执行JNI函数。堆栈信息是我们分析ANR的第一个重要的信息,一般来说:

main线程处于 BLOCK、WAITING、TIMEWAITING状态,那基本上是函数阻塞导致ANR;

如果main线程无异常,则应该排查CPU负载和内存环境。

 五、典型案例分析

 5.1 主线程执行耗时操作

  1. "main" prio=5 tid=1 Runnable
  2.   | group="main" sCount=0 dsCount=0 flags=0 obj=0x72deb848 self=0x7748c10800
  3.   | sysTid=8968 nice=-10 cgrp=default sched=0/0 handle=0x77cfa75ed0
  4.   | state=R schedstat=( 24783612979 48520902 756 ) utm=2473 stm=5 core=5 HZ=100
  5.   | stack=0x7fce68b000-0x7fce68d000 stackSize=8192KB
  6.   | held mutexes= "mutator lock"(shared held)
  7.   at com.example.test.MainActivity$onCreate$2.onClick(MainActivity.kt:20)——关键行!!!
  8.   at android.view.View.performClick(View.java:7187)
  9.   at android.view.View.performClickInternal(View.java:7164)
  10.   at android.view.View.access$3500(View.java:813)
  11.   at android.view.View$PerformClick.run(View.java:27640)
  12.   at android.os.Handler.handleCallback(Handler.java:883)
  13.   at android.os.Handler.dispatchMessage(Handler.java:100)
  14.   at android.os.Looper.loop(Looper.java:230)
  15.   at android.app.ActivityThread.main(ActivityThread.java:7725)
  16.   at java.lang.reflect.Method.invoke(Native method)
  17.   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
  18.   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)

上述日志表明,主线程正处于执行状态,看堆栈信息可知不是处于空闲状态,发生ANR是因为一处click监听函数里执行了耗时操作。

5.2 主线程被锁阻塞
 

  1. "main" prio=5 tid=1 Blocked
  2.   | group="main" sCount=1 dsCount=0 flags=1 obj=0x72deb848 self=0x7748c10800
  3.   | sysTid=22838 nice=-10 cgrp=default sched=0/0 handle=0x77cfa75ed0
  4.   | state=S schedstat=( 390366023 28399376 279 ) utm=34 stm=5 core=1 HZ=100
  5.   | stack=0x7fce68b000-0x7fce68d000 stackSize=8192KB
  6.   | held mutexes=
  7.   at com.example.test.MainActivity$onCreate$1.onClick(MainActivity.kt:15)
  8.   - waiting to lock <0x01aed1da> (a java.lang.Object) held by thread 3 ——————关键行!!!
  9.   at android.view.View.performClick(View.java:7187)
  10.   at android.view.View.performClickInternal(View.java:7164)
  11.   at android.view.View.access$3500(View.java:813)
  12.   at android.view.View$PerformClick.run(View.java:27640)
  13.   at android.os.Handler.handleCallback(Handler.java:883)
  14.   at android.os.Handler.dispatchMessage(Handler.java:100)
  15.   at android.os.Looper.loop(Looper.java:230)
  16.   at android.app.ActivityThread.main(ActivityThread.java:7725)
  17.   at java.lang.reflect.Method.invoke(Native method)
  18.   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
  19.   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
  20.    
  21.   ........省略N行.....
  22.    
  23.   "WQW TEST" prio=5 tid=3 TimeWating
  24.   | group="main" sCount=1 dsCount=0 flags=1 obj=0x12c44230 self=0x772f0ec000
  25.   | sysTid=22938 nice=0 cgrp=default sched=0/0 handle=0x77391fbd50
  26.   | state=S schedstat=( 274896 0 1 ) utm=0 stm=0 core=1 HZ=100
  27.   | stack=0x77390f9000-0x77390fb000 stackSize=1039KB
  28.   | held mutexes=
  29.   at java.lang.Thread.sleep(Native method)
  30.   - sleeping on <0x043831a6> (a java.lang.Object)
  31.   at java.lang.Thread.sleep(Thread.java:440)
  32.   - locked <0x043831a6> (a java.lang.Object)
  33.   at java.lang.Thread.sleep(Thread.java:356)
  34.   at com.example.test.MainActivity$onCreate$2$thread$1.run(MainActivity.kt:22)
  35.   - locked <0x01aed1da> (a java.lang.Object)————————————————————关键行!!!
  36.   at java.lang.Thread.run(Thread.java:919)

 这是一个典型的主线程被锁阻塞的例子; 

  1. waiting to lock <0x01aed1da> (a java.lang.Object) held by thread 3

 其中等待的锁是<0x01aed1da>,这个锁的持有者是线程 3。进一步搜索 “tid=3” 找到线程3, 发现它正在TimeWating。

那么ANR的原因找到了:线程3持有了一把锁,并且自身长时间不释放,主线程等待这把锁发生超时。在线上环境中,常见因锁而ANR的场景是SharePreference写入

5.3 CPU被抢占 

  1. CPU usage from 0ms to 10625ms later (2020-03-09 14:38:31.633 to 2020-03-09 14:38:42.257):
  2.   543% 2045/com.alibaba.android.rimet: 54% user + 89% kernel / faults: 4608 minor 1 major ————关键行!!!
  3.   99% 674/android.hardware.camera.provider@2.4-service: 81% user + 18% kernel / faults: 403 minor
  4.   24% 32589/com.wang.test: 22% user + 1.4% kernel / faults: 7432 minor 1 major
  5.   ........省略N行.....

如上日志,第二行是钉钉的进程,占据CPU高达543%,抢占了大部分CPU资源,因而导致发生ANR。

5.4 内存紧张导致ANR 

如果有一份日志,CPU和堆栈都很正常(不贴出来了),仍旧发生ANR,考虑是内存紧张。 

 系统日志里搜索am_meminfo, 这个没有搜索到。再次搜索onTrimMemory,果然发现了很多条记录;

  1. 10-31 22:37:19.749 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0
  2. 10-31 22:37:33.458 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0
  3. 10-31 22:38:00.153 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0
  4. 10-31 22:38:58.731 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0
  5. 10-31 22:39:02.816 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0

 可以看出,在发生ANR的时间点前后,内存都处于紧张状态,level等级是80,

可知80这个等级是很严重的,应用马上就要被杀死,被杀死的这个应用从名字可以看出来是桌面,连桌面都快要被杀死,那普通应用能好到哪里去呢?

一般来说,发生内存紧张,会导致多个应用发生ANR,所以在日志中如果发现有多个应用一起ANR了,可以初步判定,此ANR与你的应用无关。

5.5 系统服务超时导致ANR 

系统服务超时一般会包含BinderProxy.transactNative关键字,请看如下日志:

  1. "main" prio=5 tid=1 Native
  2.   | group="main" sCount=1 dsCount=0 flags=1 obj=0x727851e8 self=0x78d7060e00
  3.   | sysTid=4894 nice=0 cgrp=default sched=0/0 handle=0x795cc1e9a8
  4.   | state=S schedstat=( 8292806752 1621087524 7167 ) utm=707 stm=122 core=5 HZ=100
  5.   | stack=0x7febb64000-0x7febb66000 stackSize=8MB
  6.   | held mutexes=
  7.   kernel: __switch_to+0x90/0xc4
  8.   kernel: binder_thread_read+0xbd8/0x144c
  9.   kernel: binder_ioctl_write_read.constprop.58+0x20c/0x348
  10.   kernel: binder_ioctl+0x5d4/0x88c
  11.   kernel: do_vfs_ioctl+0xb8/0xb1c
  12.   kernel: SyS_ioctl+0x84/0x98
  13.   kernel: cpu_switch_to+0x34c/0x22c0
  14.   native: #00 pc 000000000007a2ac /system/lib64/libc.so (__ioctl+4)
  15.   native: #01 pc 00000000000276ec /system/lib64/libc.so (ioctl+132)
  16.   native: #02 pc 00000000000557d4 /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+252)
  17.   native: #03 pc 0000000000056494 /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+60)
  18.   native: #04 pc 00000000000562d0 /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+216)
  19.   native: #05 pc 000000000004ce1c /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+72)
  20.   native: #06 pc 00000000001281c8 /system/lib64/libandroid_runtime.so (???)
  21.   native: #07 pc 0000000000947ed4 /system/framework/arm64/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+196)
  22.   at android.os.BinderProxy.transactNative(Native method) ————————————————关键行!!!
  23.   at android.os.BinderProxy.transact(Binder.java:804)
  24.   at android.net.IConnectivityManager$Stub$Proxy.getActiveNetworkInfo(IConnectivityManager.java:1204)—关键行!
  25.   at android.net.ConnectivityManager.getActiveNetworkInfo(ConnectivityManager.java:800)
  26.   at com.xiaomi.NetworkUtils.getNetworkInfo(NetworkUtils.java:2)
  27.   at com.xiaomi.frameworkbase.utils.NetworkUtils.getNetWorkType(NetworkUtils.java:1)

从堆栈可以看出获取网络信息发生了ANR:getActiveNetworkInfo。

前文有讲过:系统的服务都是Binder机制(16个线程),服务能力也是有限的,有可能系统服务长时间不响应导致ANR。如果其他应用占用了所有Binder线程,那么当前应用只能等待。

可进一步搜索:blockUntilThreadAvailable关键字:
 

  1. at android.os.Binder.blockUntilThreadAvailable(Native method)

如果有发现某个线程的堆栈,包含此字样,可进一步看其堆栈,确定是调用了什么系统服务。此类ANR也是属于系统环境的问题,如果某类型机器上频繁发生此问题,应用层可以考虑规避策略。

参考链接:ANR日志分析全面解析_android anr 日志-CSDN博客

后面分享使用 Matrix工具去监控app卡顿

相关文章:

Android ANR 总结

工作之余&#xff0c;对之前学习到的和结合自己项目过程中的遇到的问题经验做一些总结&#xff0c;下面讲一讲Android开发过程中遇到的ANR的问题&#xff0c;做一下整理 一、概述 解决ANR一直是Android 开发者需要掌握的重要技巧&#xff0c;一般从三个方面着手。 开发阶段&a…...

群晖Drive搭建云同步服务器结合内网穿透实现Obsidian笔记文件远程多端同步

文章目录 一、简介软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步1 安装并设置Synology Drive套件2 局域网内同步文件测试 三、内网穿透群晖Synology Drive&#xff0c;实现异地多端同步Windows 安装 Cpolar步骤&#…...

Flutter中的图片查看器:使用photo_view库

在移动应用开发中&#xff0c;图片查看器是一个常见的需求。Flutter提供了许多库来简化这一过程&#xff0c;其中photo_view库是一个强大而灵活的选择。本文将介绍photo_view库的基本概念以及如何在Flutter应用中使用它来实现漂亮的图片查看体验。 1. 什么是photo_view库&…...

软件测试|使用Python轻松裁剪视频

简介 裁剪视频是在视频编辑和处理中常见的任务之一&#xff0c;Python提供了多种库和工具&#xff0c;可以用来裁剪视频。在本文中&#xff0c;我们将详细讨论如何使用Python来裁剪视频&#xff0c;并提供示例代码。 步骤1&#xff1a;环境准备 首先&#xff0c;我们要安装必…...

计算机网络——运输层(1)暨小程送书

计算机网络——运输层&#xff08;1&#xff09;暨小程送书 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 运输层概述两个主要协议运输层和网络层的关系网络层运输层总结 多路复用与多路分解多路复用多路分解不同的技术实现时分复用&#xff08;TDM&#xff09;频分复…...

中国互联网的早期形态

1 大约是从 1991 年开始&#xff0c;国内开始了第一个 BBS 站——北京长城站&#xff0c;经过长时间发展&#xff0c;直到 1995 年&#xff0c;随着计算机及其外设的大幅降价&#xff0c;BBS 才逐渐被部分人们所认识。少数玩 BBS 站的“极客”站长&#xff0c; 基于个人关系&am…...

机场数据治理系列介绍(3):从数据到资产认定过程要搞懂的一些概念

目录 一、从数据到资产的基本背景 1、国家政策方面的梳理 2、地方政府的摸索实践梳理 二、数据资产化相关概念 1、数据 2、资产 3.、数据资产 4、数据资产入表 5、数据资源VS数据资产 三、关于《企业数据资源相关会计处理暂行规定》的相关解读 1、《暂行规定》不涉及…...

《C++入门篇》——弥补C不足

文章目录 前言一.命名空间二.缺省参数三.函数重载四.引用4.1引用做参数4.2引用做返回值 五.内联函数六.小语法6.1auto6.2范围for6.3空指针 前言 C是业内一门久负盛名的计算机语言&#xff0c;从C语言发展起来的它&#xff0c;不仅支持C语言的语法&#xff0c;还新添加了面向对…...

要在Linux上安装Docker Compose和nginx

一、要在Linux上安装Docker Compose&#xff0c;您可以按照以下步骤进行操作&#xff1a; 确保您的Linux系统已经安装了Docker。您可以通过运行以下命令来检查Docker是否已经安装&#xff1a; docker --version如果Docker未安装&#xff0c;请先安装Docker。 下载Docker Compo…...

zsh插件之gitignore安装使用教程

安装 zsh 插件管理工具 首先&#xff0c;确保你已经安装了 zsh&#xff0c;然后安装 Oh My Zsh&#xff0c;这是一个流行的 zsh 配置框架。在终端运行以下命令安装 Oh My Zsh&#xff1a; bashCopy code sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/ma…...

十二、Qt 操作PDF文件(2)

一、在《十、Qt 操作PDF文件-CSDN博客》中我们用Poppler类库打开了PDF文件&#xff0c;并显示到窗体上&#xff0c;但只能显示一页&#xff0c;功能还没完善&#xff0c;在本章节中&#xff0c;加入了&#xff1a; 通过选择框选择PDF文件并打开&#xff0c;默认打开第一页。通…...

Flutter系列:Flutter常见问答(可用于面试)

Flutter系列 Flutter常见问答 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/135604801 【简介】&#…...

聚合收益协议 InsFi :打开铭文赛道全新叙事的旋转门

​“InsFi 协议构建了一套以铭文资产为基础的聚合收益体系&#xff0c;该体系正在为铭文资产捕获流动性、释放价值提供基础&#xff0c;该生态也正在成为铭文赛道掘金的新热土。” 在 2023 年年初&#xff0c;Ordinals 协议在比特币链上被推出后&#xff0c;为比特币链上带来了…...

【信号与系统】【北京航空航天大学】实验三、连续时间信号的频域分析 【MATLAB】

一、实验目的 1、掌握 傅立叶变换&#xff08;The Fourier Transform&#xff09; 及其性质&#xff1b; 2、掌握连续时间信号傅立叶变换的数值计算方法&#xff1b; 3、掌握利用 MATLAB 实现信号的幅度调制&#xff08;Amplitude Modulation, AM&#xff09; 的方法&#xff…...

FFmpeg之AVFilter

文章目录 一、概述二、重要结构体2.1、AVFilterGraph2.2、AVFilter2.3、AVFilterContext 三、流程梳理3.1、FFmpeg AVFilter 使用整体流程3.2、过滤器构建流程3.2.1、分配AVFilterGraph3.2.2、创建过滤器源3.2.3、创建接收过滤器3.2.4、生成源和接收过滤器的输入输出3.2.5、通过…...

ES 之索引和文档

本文主要介绍ES中的数据组成结构单元。 一、文档(Document) 1、概念 ES的数据存储单元是面向文档的&#xff0c;文档是所有数据存储&#xff0c;搜索的最小单元。 你可以把ES中的文档对应成mysql中的一条条数据记录。到时候你存进ES的数据就是一个个文档。 文档存入ES是序列…...

使用muduo库编写网络server端

muduo库源码编译安装和环境搭建 C muduo网络库知识分享01 - Linux平台下muduo网络库源码编译安装-CSDN博客 #include<iostream> #include<muduo/net/TcpServer.h> #include<muduo/net/EventLoop.h> using namespace std; using namespace muduo; using name…...

Unity3D和three.js的比较

一、Unity3D和three.js简介 Unity3D是一款跨平台的游戏引擎,可以用于开发2D和3D游戏。它提供了一个可视化的开发环境,包含了强大的编辑器和工具,使开发者可以方便地创建游戏场景、添加物体、设置物理效果、编写脚本等。Unity3D支持多种平台,包括PC、移动设备、主机等,可以…...

JavaScript 类型判断及类型转换规则

文章目录 JavaScript 类型及其判断使用 typeof 判断类型使用 instanceof 判断类型使用 constructor 和 Object.prototype.toString 判断类型JavaScript 类型及其转换JavaScript 函数参数传递cannot read property of undefined 问题解决方案分析一道网红题目JavaScript 类型判断…...

ubuntu禁用/启用图形界面

当安装了带图形界的ubuntu的时候&#xff0c;如果觉得图形界面占资源&#xff0c;就需要将图形界面关闭&#xff0c;关闭的方法如下&#xff1a; 1、 打开 /etc/default/grub&#xff0c;修改或增加如下参数&#xff1a; GRUB_CMDLINE_LINUX_DEFAULT"text" GRUB_TE…...

【LeetCode】28. 找出字符串中第一个匹配项的下标(简单)——代码随想录算法训练营Day09

题目链接&#xff1a;28. 找出字符串中第一个匹配项的下标 题目描述 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff…...

架设一台NFS服务器

1、开放/nfs/shared目录&#xff0c;供所有用户查询资料 2、开放/nfs/upload目录&#xff0c;为192.168.xxx.0/24网段主机可以上传目录&#xff0c; 并将所有用户及所属的组映射为nfs-upload,其UID和GID均为210 3、将/home/tom目录仅共享给192.168.xxx.xxx这台主机&#xf…...

MySQL中根据出生日期计算年龄

创建student表 mysql> create table student( -> sid int primary key comment 学生号, -> sname varchar(20) comm…...

ABAP IDOC 2 XML

有个需求&#xff0c;外围系统希望我们给到一个IDOC 记录的样例&#xff0c;但是我们we02中并无法看到 就找了一个demo去直接展示IDOC内容 *&---------------------------------------------------------------------* *& Report Z_IDOC_TO_XML *&------------…...

什么是小程序?特点和技术架构详解

小程序是一种新的移动应用程序格式&#xff0c;一种结合了 Web 技术以及客户端技术的混合解决方案。 传统的原生应用运行起来比较流畅&#xff0c;但是也有天然的基因缺陷&#xff1a; 不支持动态化&#xff0c;发布周期长需要开发Android和iOS两套代码&#xff0c;开发成本高…...

边缘计算的挑战和机遇——数据安全与隐私保护

边缘计算的挑战和机遇 边缘计算面临着数据安全与隐私保护、网络稳定性等挑战&#xff0c;但同时也带来了更强的实时性和本地处理能力&#xff0c;为企业降低了成本和压力&#xff0c;提高了数据处理效率。因此&#xff0c;边缘计算既带来了挑战也带来了机遇&#xff0c;需要我…...

linux-等保三级脚本(1)

该脚本主要是针对 CentOS Linux 7 合规基线加固的一些配置操作&#xff0c;包括创建用户、安全审计配置、入侵防范配置、访问控制配置、身份鉴别策略配置等。如果您需要在脚本中添加公司网址&#xff0c;您可以在适当的位置添加相应的内容。不过请注意&#xff0c;在实际生产环…...

K8s面试题——情景篇

文章目录 一、考虑一家拥有分布式系统的跨国公司&#xff0c;拥有大量数据中心&#xff0c;虚拟机和许多从事各种任务的员工。您认为这样公司如何以与 Kubernetes 一致的方式管理所有任务?二、考虑一种情况&#xff0c;即公司希望通过维持最低成本来提高其效率和技术运营速度。…...

.NET 8.0 发布到 IIS

如何在IIS&#xff08;Internet信息服务&#xff09;上发布ASP.NET Core 8&#xff1f; 在本文中&#xff0c;我假设您的 Windows Server IIS 上已经有一个应用程序池。 按照步骤了解在 IIS 环境下发布 ASP.NET Core 8 应用程序的技巧。 您需要设置代码以支持 IIS 并将项目配…...

当前vscode环境下 多进程多线程运行情况探究

我的代码 其中在“打开图片时”、“进入子进程之前”、“子进程join前”、“进入子进程区域后”&#xff0c;“子进程join后”、“进入子线程区域后”分别打印了进程线程的编号和数量。 # -*- coding: utf-8 -*-# Form implementation generated from reading ui file test2.…...