最近新版本上線搓逾,測(cè)試同學(xué)新寫了個(gè)變態(tài)的測(cè)試腳本去測(cè)試我們應(yīng)用的性能掸掏,結(jié)果遇到了一個(gè)非常詭異的現(xiàn)象,當(dāng)app運(yùn)行一定的次數(shù)之后拜马,就會(huì)崩潰考抄,由于我們是系統(tǒng)應(yīng)用细疚,崩潰之后,系統(tǒng)會(huì)重新拉起APP川梅。所以該問題一直沒有暴露出來。直到最近然遏。
日志
oom的相關(guān)日志
06-17 22:25:48.366 12937 12937 W System.err: java.lang.OutOfMemoryError: Could not allocate JNI Env
06-17 22:25:48.366 12937 12937 W System.err: at java.lang.Thread.nativeCreate(Native Method)
06-17 22:25:48.366 12937 12937 W System.err: at java.lang.Thread.start(Thread.java:730)
...
引發(fā)oom的相關(guān)日志
06-11 06:15:20.981 13253 31854 F Looper : Could not create epoll instance: Too many open files
先解釋第二條日志的原因贫途,linux系統(tǒng)對(duì)于每個(gè)進(jìn)程能夠操作的文件句柄數(shù)量有一個(gè)上限,通常是1024待侵,如果超過了這個(gè)上限丢早,就會(huì)崩潰。我們平時(shí)的操作秧倾,比如文件怨酝,數(shù)據(jù)庫(kù)的讀寫,bitmap的加載那先,以至于socket的打開關(guān)閉农猬,so文件,dex文件的讀取售淡,都會(huì)直接影響這個(gè)句柄數(shù)量的增減斤葱。如下
package.name 15713 system mem REG 259,22 806688 934478 /data/data/ package.name/app_SGLib/libsgmainso-5.1.96.so
package.name 15713 system mem unknown /dev/ashmem/dalvik-CompilerMetadata (deleted)
package.name 15713 system mem REG 259,20 10952 2308 /system/lib64/libscreencapture_jni.so
package.name 15713 system mem unknown /dev/ashmem/dalvik-indirect ref table (deleted)
package.name 15713 system mem REG 259,22 221824 1310962 /data/app/ package.name-vfKvuMdB9mVCsGbB4t_mCg==/oat/arm64/base.odex
package.name 15713 system mem REG 259,22 11836592 1310965 /data/app package.name-vfKvuMdB9mVCsGbB4t_mCg==/oat/arm64/base.vdex
package.name 15713 system 154u 0000 0,10 0t0 6783 anon_inode:[eventfd]
package.name 15713 system 155u 0000 0,10 0t0 6783 anon_inode:[eventpoll]
package.name 15713 system 156w REG 259,22 3241 934842 /data/data/package.name/cache/image_manager_disk_cache/journal
package.name 15713 system 91u REG 259,22 28672 942294 /data/data/com.hisense.smartimages/databases/report.db
package.name 15713 system 92u sock 0t0 192613 socket:[192613]
package.name 15713 system 93u sock 0t0 193069 socket:[193069]
解決思路
OOM的原因很簡(jiǎn)單慷垮,就是內(nèi)部類持有了外部類的引用未及時(shí)釋放,導(dǎo)致了每次都會(huì)新增內(nèi)存揍堕,但是深入的分析料身,就是文件句柄超出了數(shù)量限制。
既然是打開了太多的文件衩茸,則意味著某個(gè)地方的文件資源或者內(nèi)存未釋放芹血,導(dǎo)致了如上兩個(gè)問題,接下來就是問題排查楞慈,如果想要排查文件增減祟牲,可以通過如下命令
adb shell
ps -A //查看對(duì)應(yīng)應(yīng)用的pid
cd/proc/pid/fd //進(jìn)入指定目錄下
ls -l|wc -l //查看句柄數(shù)增減情況
lsof -p pid //查看詳細(xì)的句柄信息
需要一點(diǎn)一點(diǎn)的注釋代碼,排查產(chǎn)生句柄的代碼抖部,縮小范圍说贝,然后查看如何導(dǎo)致的內(nèi)存泄漏。