现象:银行柜台上的android应用程序,用于客户进行电子签名,客户签名一定次数后,程序运行出现错误。
分析:因为程序总是签名这个操作执行一定次数后出现错误,而且错误可复现,初步断定是内存方面的问题,查了虚拟机,没发现内存使用不当之处,但对签名程序进行分析发现程序使用了一个组件,用于处理pdf文档,而这个组件又执行了so程序,用adb登录到android系统,查看系统内存使用情况:
$cat /proc/meminfo
MemTotal: 1015256 kB
MemFree: 247544 kB
Buffers: 10552 kB
Cached: 402084 kB
SwapCached: 0 kB
Active: 203524 kB
Inactive: 353324 kB
Active(anon): 144224 kB
Inactive(anon): 204 kB
Active(file): 59300 kB
Inactive(file): 353120 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 520908 kB
SwapFree: 520908 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 144212 kB
Mapped: 90972 kB
Shmem: 244 kB
Slab: 37924 kB
SReclaimable: 14468 kB
SUnreclaim: 23456 kB
KernelStack: 10944 kB
PageTables: 8732 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 1028536 kB
Committed_AS: 16506272 kB
VmallocTotal: 251658176 kB
VmallocUsed: 114896 kB
VmallocChunk: 251473856 kB
仔细观察上面的MemFree项,在每次执行签名操作后值都在减少,而且签名操作完成后,减少的部分也不会得到回复,直至减小到系统的阈值后,程序运行异常,据此得知,在android签名程序中执行原生代码,造成系统内存泄漏。
解决方案:由于签名操作在处理pdf文档时用的是第三方组件,无法通过修改或优化程序的方法解决问题,而客户的签名操作程序启动后要求一直的处于运行状态,泄漏的内存不会及时得到释放,故而需另辟蹊径。最终解决方案:把签名程序从原来的进程中剥离出来,需要签名的时候以另外的进程身份运行签名程序,签名完成后,马上结束这个进程,从而泄漏的内存得到释放,问题解决。
以独立的进程身份运行android应用,只需在AndroidManifest.xml中这样定义activity即可。
<activity
android:name="com.inhuasoft.page.SignActivity"
android:process="com.inhuasoft.page.SignActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
</activity>