建設(shè)部網(wǎng)站四庫一平臺(tái)best網(wǎng)絡(luò)推廣平臺(tái)
android FD_SET_chk問題定位
- 一、FD報(bào)錯(cuò)
- 二、問題定位
- 2.1 APM定位
- 2.2 adb定位
- 2.3. 代碼獲取FD數(shù)
- 三、FD優(yōu)化
一、FD報(bào)錯(cuò)
App在運(yùn)行中記錄報(bào)錯(cuò)如下,FD_SET,這個(gè)問題大概是文件描述符(File Descriptor,簡(jiǎn)稱FD)超過了最大限制數(shù),說明App內(nèi)可能存在FD泄漏。
二、問題定位
2.1 APM定位
由于App使用了火山APM監(jiān)測(cè),找到此對(duì)應(yīng)崩潰信息中的Native信息,可以看到FD歸類,已超過1024個(gè)(每個(gè)手機(jī)的可打開的最大FD不同)。而大部分集中在data中,data里存在大量創(chuàng)建文件沒有關(guān)閉造成FD超過1024.
2.2 adb定位
// 1.先查詢到App包名對(duì)應(yīng)的pid
adb shell ps
// 2.cat /proc/pid/limits 查看最大可開啟的文件數(shù),找到open files (FD)、lock files (文件鎖)// 3. adb shell ls -l /proc/pid/fd,需要root權(quán)限
adb shell ls -l /proc/988/fd
2.3. 代碼獲取FD數(shù)
- 使用StrictMode框架定位具體代碼占用fd,搜索日志TAG StrictMode 定位出問題的代碼
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build())StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build())
- 直接代碼獲取fd數(shù)
private fun printFdInfo() {val pid = android.os.Process.myPid()val fdDir = File("/proc/$pid/fd")if (fdDir.isDirectory) {val files = fdDir.listFiles()if (files != null) {Log.d("FD_INFO", "進(jìn)程 " + pid + " 當(dāng)前打開的文件描述符數(shù)量: " + files.size)for (file in files) {try {val filePath = file.canonicalPathLog.d("FD_INFO", "文件描述符: " + file.name + " -> " + filePath)} catch (e: IOException) {Log.e("FD_INFO", "獲取文件描述符信息失敗", e)}}}} else {Log.e("FD_INFO", "無法訪問 /proc/$pid/fd 目錄")}}
三、FD優(yōu)化
- 數(shù)據(jù)庫不要過多,數(shù)據(jù)庫設(shè)計(jì)要精簡(jiǎn)合理,App退出時(shí)及時(shí)關(guān)閉
- 文件操作完畢后,要及時(shí)close
- 避免大量創(chuàng)建文件,使用緩存的文件進(jìn)行操作
- Socket請(qǐng)求、Http請(qǐng)求盡量避免輪詢