记一次android特殊的OOM经历

最近新版本上线,测试同学新写了个变态的测试脚本去测试我们应用的性能,结果遇到了一个非常诡异的现象,当app运行一定的次数之后,就会崩溃,由于我们是系统应用,崩溃之后,系统会重新拉起APP。所以该问题一直没有暴露出来。直到最近。
日志 oom的相关日志

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) ...

引发oom的相关日志
06-11 06:15:20.981 13253 31854 F Looper: Could not create epoll instance: Too many open files

先解释第二条日志的原因,linux系统对于每个进程能够操作的文件句柄数量有一个上限,通常是1024,如果超过了这个上限,就会崩溃。我们平时的操作,比如文件,数据库的读写,bitmap的加载,以至于socket的打开关闭,so文件,dex文件的读取,都会直接影响这个句柄数量的增减。如下
package.name 15713systemmemREG259,22806688934478 /data/data/package.name/app_SGLib/libsgmainso-5.1.96.so package.name 15713systemmemunknown/dev/ashmem/dalvik-CompilerMetadata (deleted) package.name 15713systemmemREG259,20109522308 /system/lib64/libscreencapture_jni.so package.name 15713systemmemunknown/dev/ashmem/dalvik-indirect ref table (deleted) package.name 15713systemmemREG259,222218241310962 /data/app/package.name-vfKvuMdB9mVCsGbB4t_mCg==/oat/arm64/base.odex package.name 15713systemmemREG259,22118365921310965 /data/apppackage.name-vfKvuMdB9mVCsGbB4t_mCg==/oat/arm64/base.vdex package.name 15713system154u00000,100t06783 anon_inode:[eventfd] package.name 15713system155u00000,100t06783 anon_inode:[eventpoll] package.name 15713system156wREG259,223241934842 /data/data/package.name/cache/image_manager_disk_cache/journal package.name 15713system91uREG259,2228672942294 /data/data/com.hisense.smartimages/databases/report.db package.name 15713system92usock0t0192613 socket:[192613] package.name 15713system93usock0t0193069 socket:[193069]

解决思路 OOM的原因很简单,就是内部类持有了外部类的引用未及时释放,导致了每次都会新增内存,但是深入的分析,就是文件句柄超出了数量限制。
既然是打开了太多的文件,则意味着某个地方的文件资源或者内存未释放,导致了如上两个问题,接下来就是问题排查,如果想要排查文件增减,可以通过如下命令
adb shell ps -A //查看对应应用的pid cd/proc/pid/fd //进入指定目录下 ls -l|wc -l //查看句柄数增减情况 lsof -p pid //查看详细的句柄信息

【记一次android特殊的OOM经历】需要一点一点的注释代码,排查产生句柄的代码,缩小范围,然后查看如何导致的内存泄漏。

    推荐阅读