Android Memory/Resource Leak总结
来源:互联网 发布:随机森林算法软件 编辑:程序博客网 时间:2024/06/11 02:48
Android的内存/资源泄露,不容易发现,又会引发app甚至是system的一系列问题。
在这里我根据以往碰到的相关问题,总结出了一些检测和修改方法。
*有可能造成memory leak的代码是Framework层的文件,但最终影响了App层的进程;
所以发现app进程出现memory leak的时候,也要考虑Framework层是否有问题。
*确保一定close资源:try { return; } finally { resource.close(); } 这样即使try块中有return语句,也能保证finally块中的close被执行到。
*resource leak的检查需要启动StrictMode。
1.文件IO没有关闭
现象:对app进行重复“进入-退出”的自动化测试,500+次之后出现ANR。
E/StrictMode( 618): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.E/StrictMode( 618): java.lang.Throwable: Explicit termination method 'close' not calledE/StrictMode( 618): at dalvik.system.CloseGuard.open(CloseGuard.java:184)E/StrictMode( 618): at java.io.FileInputStream.<init>(FileInputStream.java:80)E/StrictMode( 618): at java.io.FileReader.<init>(FileReader.java:42)E/StrictMode( 618): at android.net.http.AndroidHttpClient.fun3(AndroidHttpClient.java:) <- 出错位置E/StrictMode( 618): at android.net.http.AndroidHttpClient.fun2(AndroidHttpClient.java:)E/StrictMode( 618): at android.net.http.AndroidHttpClient.fun1(AndroidHttpClient.java:)E/StrictMode( 618): at com.android.server.location.GpsXtraDownloader.doDownload(GpsXtraDownloader.java:143)E/StrictMode( 618): at com.android.server.location.GpsXtraDownloader.downloadXtraData(GpsXtraDownloader.java:100)E/StrictMode( 618): at com.android.server.location.GpsLocationProvider$6.run(GpsLocationProvider.java:1023)E/StrictMode( 618): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)E/StrictMode( 618): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)E/StrictMode( 618): at java.lang.Thread.run(Thread.java:841)
这种错误不会被容易察觉,但可以避免或在前期找出错误。
小结:
a.不再使用的文件IO要调用close()释放;
b.搜索Log中是否有"release", "leak", "java.io.Closeable"等关键词;
c.BufferedReader br = new BufferedReader(new FileReader(file)); close掉BufferedReader也会隐式close掉FileReader;
d.可能有频繁GC,造成屏幕画面卡顿(如Rotation):
12-06 13:44:13.970 9552 9556 E dalvikvm: 9552(com.test.app) stat: (e) 63 937KB / (c) 11 31MB / (a) 4 13MB / (h) 15MB 20MB 4485KB12-06 13:44:13.970 9552 9556 D dalvikvm: GC_CONCURRENT freed 8183K, 32% free 23967K/34952K, paused 4ms+25ms, total 150ms12-06 13:44:13.970 9552 9652 D dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 156ms12-06 13:44:13.970 9552 9654 D dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 155ms12-06 13:44:13.970 9552 9658 D dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 156ms12-06 13:44:13.970 9552 9656 D dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 156ms12-06 13:44:13.975 9552 9660 D dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 157ms12-06 13:44:13.980 9552 9561 E StrictMode: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.12-06 13:44:13.980 9552 9561 E StrictMode: java.lang.Throwable: Explicit termination method 'close' not called12-06 13:44:13.980 9552 9561 E StrictMode: at dalvik.system.CloseGuard.open(CloseGuard.java:184)12-06 13:44:13.980 9552 9561 E StrictMode: at java.io.FileInputStream.<init>(FileInputStream.java:80)12-06 13:44:13.980 9552 9561 E StrictMode: at com.test.app.*(Unknown Source)
2.Cursor没有关闭
现象:自动化测试800+次以后手机reboot
E/StrictMode( 3814): Finalizing a Cursor that has not been deactivated or closed. database = /data/data/com.test.app/databases/..., table = null, query = SELECT * FROM table WHERE package = '';E/StrictMode( 3814): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened hereE/StrictMode( 3814): at android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:98)E/StrictMode( 3814): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:50)E/StrictMode( 3814): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1436)E/StrictMode( 3814): at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1375)E/StrictMode( 3814): at com.test.app.*(Unknown Source)
小结:
a.过多cursor会造成Excessive JNI global references,导致system_server的VM aborting
b.Log关键词:"DatabaseObjectNotClosedException"
3. InputChannel fd过多
现象:压力测试反复打开关闭某App 200~300次后出现FC
03-07 15:37:56.334 E/AndroidRuntime( 5338): FATAL EXCEPTION: main03-07 15:37:56.334 E/AndroidRuntime( 5338): Process: com.app.foo, PID: 533803-07 15:37:56.334 E/AndroidRuntime( 5338): java.lang.RuntimeException: Could not read input channel file descriptors from parcel.03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.view.InputChannel.nativeReadFromParcel(Native Method)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.view.InputChannel.readFromParcel(InputChannel.java:148)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.view.IWindowSession$Stub$Proxy.addToDisplay(IWindowSession.java:717)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.view.ViewRootImpl.setView(ViewRootImpl.java:727)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:278)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3061)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.app.ActivityThread.access$900(ActivityThread.java:169)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1277)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.os.Handler.dispatchMessage(Handler.java:102)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.os.Looper.loop(Looper.java:136)03-07 15:37:56.334 E/AndroidRuntime( 5338): at android.app.ActivityThread.main(ActivityThread.java:5476)03-07 15:37:56.334 E/AndroidRuntime( 5338): at java.lang.reflect.Method.invokeNative(Native Method)03-07 15:37:56.334 E/AndroidRuntime( 5338): at java.lang.reflect.Method.invoke(Method.java:515)03-07 15:37:56.334 E/AndroidRuntime( 5338): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)03-07 15:37:56.334 E/AndroidRuntime( 5338): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)03-07 15:37:56.334 E/AndroidRuntime( 5338): at dalvik.system.NativeStart.main(Native Method)
分析:
App的input event由WindowManagerService管理,WMS会内部创建一个InputManager,两者的连接通过InputChannel来完成。
WMS需要注册两个InputChannel与InputManager连接,其中Server端InputChannel注册在InputManager(SystemServer进程)当中,Client端注册在应用程序主线程中。
InputChannel使用Ashmem匿名共享内存来传递数据,它由一个fd文件描述符指向,同时read端和write端各占用一个fd。
当我们打开一个app时,设置log的tag为"InputTransport",可以看到server(system_server)和client(app)都会construct fd。
809 InputTransport Input channel constructed: name='426d6588 com.app.phone/com.app.phone.ActivityWelcome (server)', fd=43119501 InputTransport Input channel constructed: name='426d6588 com.app.phone/com.app.phone.ActivityWelcome (client)', fd=58
实际案例:
当startActivity的intent flag被设置为Intent.FLAG_ACTIVITY_MULTIPLE_TASK类似flag的时候,如果没有处理好Activity的生命周期,
就会造成Activity无法回收(RecentApps中大量的task),而所占用的fd指向的ashmem也无法释放(errno = 24),就会造成上述问题。
参考自:http://www.cnblogs.com/jacobchen/p/3568151.html
- Android Memory/Resource Leak总结
- Android Memory/Resource Leak总结
- Android memory leak detection
- Android Handler Memory Leak
- Android memory leak analysis
- Android memory leak
- Android memory leak detect
- (Memory and Resource) Leak detection for WinCE
- Android memory leak using MAT
- android webview memory leak 线索
- android memory leak analysis tools
- memory leak checking for android
- Android native memory leak debug
- android memory leak ==java memory leak
- Memory Leak(内存泄漏)问题总结
- Memory Leak(内存泄漏)问题总结
- Memory Leak
- memory leak
- 树状数组理论与实现
- C# 二分查找
- 全志行车记录仪里面FireEyepublic.apk反编译的分析(三)——TTS语音播报
- 通过金矿模型介绍动态规划
- javascript 数字字符串与数字的转换
- Android Memory/Resource Leak总结
- reference :引用
- List中笔记
- WIN7下VS2008 LINK : fatal error LNK1000: Internal error during IncrBuildImage
- xcode6缩小storyboard方法
- Android 组件系列-----Activity的传值和回传值
- ProgressBar 整理
- Oracle 数据库 查询 执行sql语句的机器名
- Android 二维码 生成和识别(附Demo源码)