IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android数据库Cursor异常原因和Fd泄露分析 -> 正文阅读

[移动开发]Android数据库Cursor异常原因和Fd泄露分析

前言

手机应用和Android终端机应用不同的地方是:Android终端机应用长时间运行,必须保证长时间(几周到几个月不等)稳定运行,不崩溃,而手机应用经常进出,很难发现一些问题。线下监控内存泄漏可以使用LeakCanary、Android Studio 的 Android Profiler、eclispe的MAT这些常规手段,但是不支持线上监控。线上监控应用,可以使用腾讯Bugly友盟。但是有了线上监控就完事了,不一定,有时候出现一些奇怪的问题,明明看似代码规范,却还是crash了。Android终端机应用crash回到桌面(通过守护进程重新拉起应用),这是非常影响用户体验的。下面举例子分析一个常见的线上异常(数据库用的是Room

出现异常 CursorWindowAllocationException

CursorWindowAllocationException Cursor window allocation of 2048 kb failed.

可能原因1:

sqlite query完成之后cursor没有关闭。

解决方法:

在finally中关闭cursor

Cursor cursor = null;
try {
	
} finally {
	if (cursor != null) {
		cursor.close();
	}
}

可能原因2

Cursor空间耗尽,比如

线程A执行到1处创建了一个Cursor,然后dosomething比较耗时…,线程B又来查询数据库,因此到1处又创建一个Cursor,此时如果AB执行完,就会关闭锁,看起来没有问题,但由于是同一个对象,所以AB关闭的cursor都是B创建的,因此
A创建的Cursor就没有关闭!

解决方法同上

进一步分析异常

在你的应用中,Cursor正常关闭,还是时不时报CursorWindowAllocationException,这是你就要注意应用的句柄泄露了(Fd泄露),文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。

在Linux中一个文件、一个串口、一个socket、一个线程都可以是一个文件,而一个文件会占用一个句柄,linux中一个进程默认的句柄最大数值是1024,当超过这个数值,linux就会对当前的进程进行kill,而kill的对象可以是任意对象,所以会造成各种异常原因的崩溃。

Linux中, 每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而 fd 是这个数组的下标。

我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作。

既然是数组下标,fd的类型为int, < 0 为非法值, >=0 为合法值。在linux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通过设置,改变最大值。

在linux中,值为0、1、2的fd,分别代表标准输入、标准输出、标准错误输出。因为 0 1 2已经被linux使用了,通常在程序中打开的fd,是从3开始的。但我们在判断一个fd是否合法时,依然要使用>=0的判断标准。fd的分配原则,是从小到大,找到第一个不用的进行分配。

句柄泄露可能原因:

  • socket socket()/accept();
  • 数据库sqlite游标操作
  • 文件流操作,检查后都有close;
  • 硬件通讯,如串口,usb这些,是否正常关闭

通过排查,发现串口通讯没有正常关闭,创建太多fd,导致fd耗尽,最终影响数据库sqlite游标操作,出现了上面的异常CursorWindowAllocationException,数据Cursor创建也需要fd。

但是线上监控只是上报异常,没有指出哪里泄露,这时候需要通过物联网(IoT) MQTT(构建于Tcp/Ip协议的一种应用层协议,它的全称是Message Queuing Telemetry Transport)下发指令(adb)拉取fd信息,然后从终端设备上传到本地,再分析fd信息进行排查是哪里泄露。Java发送adb指令可以通过Runtime.getRuntime().exec()发送,再读取,需要注意发送的指令是否需要Root权限和结束符

Fd查询

1)Linux系统下,所有进程允许打开的最大fd数量。查询语句:

/proc/sys/fs/file-max

2)Linux系统下,所有进程已经打开的fd数量及允许的最大数量。查询语句:

/proc/sys/fs/file-nr

3)单个进程允许打开的最大fd数量.查询语句:

ulimit -n

4)单个进程(例如进程id为5454)已经打开的fd.查询语句:

ls -l /proc/5454/fd

操作步骤:

adb shell
su


查看app包名的pid
ps | grep com.sjl.test

u0_a280   11218 243   2997124 275288 SyS_epoll_ 7795a0eb80 S com.sjl.test

注意:11218就是pid

查看pid为3617的当前句柄数
ls -l /proc/3617/fd | wc -l
列出句柄被占用详细情况
ls -l /proc/3617/fd

or 进入目录查看

切换到15429进程的FD目录下
cd /proc/15429/fd

然后在查看当前FD目录下文件描述符数量:
ls -l | wc -l

94

通过观察查询文件描述符,如果文件描述符并没有被释放,说明这时候出现了FD泄露

小结

Fd泄露并不容易发现,但是规范编码,能减少大部分异常的发生,这是非常重要的。

下面是列出一些常见的优化和性能检测手段

  • 内存泄露检测工具: LeakCanary 、Android Studio 的 Android Profiler 、eclispe的MAT
    注意:memory leak会最终会导致out of memory。

  • 检测在主线程运行的操作时长(卡顿检测):BlockCanary

  • 检测方法耗时:Hugo(基于AOP实现)

  • 检测工具,APP研发助手:dokit

  • Native层崩溃的监听工具:BreakPad(不支持线上)

  • Native Crash + Java Exception检测工具:Bugly(线上检测工具)、xCrash(不支持线上)

  • 性能分析工具:TraceView、SysTrace(SysTrace用于收集可帮助您检查原生系统进程的详细系统级数据,例如CPU调度、磁盘活动、应用线程等,并解决掉帧引起的界面卡顿)

TraceView:

- 	通过Android studio自带的traceview查看(Android profiler)。
- 	通过Android SDK自带的Debug。(导出 trace 文件,通过Android Studio的profile打开该文件,可以知道有多少线程、具体方法的耗时)
- 	通过DDMS中的traceview查看。

SysTrace:

在代码的开始位置加上tag

 TraceCompat.endSection();

然后指定位置结束,即可以抓取到整个应用在此过程的相关信息

TraceCompat.beginSection("onCreate");
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:46:08  更:2022-10-17 12:49:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 3:53:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码