在内存密集型活动

时间:2016-02-09 19:10:46

标签: android memory-leaks

摘要

我使用的Android应用程序,作为其功能之一,涉及用户标记图像并保存它。此过程涉及一些重型画布drawImage()调用(有时在大约12 MB的图像上+未压缩)以及大量的数据编码和解码。图像数据也缓存在Android文件系统中,并通过JavaScriptInterface从Java传递到JavaScript。

但是,使用运行Android 5.0.2的LG G Pad X8.3,我们会遇到很多崩溃。当它崩溃时,日志显示“赢死”并返回主屏幕而不显示任何“不幸,___已停止”消息。我们的“胜利死亡”之前是InputMethod的胜利死亡,之前是com.lge.launcher2.Launcher的“胜利死亡”。这是间歇性的,但经常发生这个问题。

详情

(1)似乎是在重度图像保存操作之后发生,而不是在

之后立即发生

(2)当键盘出现时,它会更频繁地发生。有关于调高键盘导致它崩溃的事情吗?

(3)在应用程序运行时观察Android Studio中的内存使用情况时,没有什么是不寻常的。当它崩溃时,图表中仍然有可用的内存。

(3)我们尝试在清单中使用largeHeap,但这并没有消除崩溃。

(4)内存使用量在10到20 MB之间。

(5)在Web视图崩溃之前,我可以向JavaScript数组添加大约3200万个数字。这至少是240 MB(每个JS编号8个字节)。当它崩溃时,它显示一个空白屏幕,而不是我试图修复它将你带回主屏幕的崩溃。

(6)在这个版本的Android中有一个很好的公开内存泄漏(实际上是一对),但是LG没有为这个模型提供升级。

(7)我们已经尝试优化代码以尽可能少地使用内存,但崩溃仍然存在。

(8)崩溃日志始终包含崩溃周围的类似信息。

02-08 12:13:01.642    1850-1850/? I/PhoneApp﹕ onTrimMemory: 5
02-08 12:13:01.642    1850-1850/? I/PhoneApp﹕ trim memory
02-08 12:13:01.652      945-965/? I/ActivityManager﹕ Process com.google.android.partnersetup (pid 23908) has died
02-08 12:13:01.682    945-16584/? I/ActivityManager﹕ Process com.google.android.apps.plus (pid 23756) has died
02-08 12:13:01.692    1850-1850/? I/PhoneApp﹕ onTrimMemory: 10
02-08 12:13:01.692    1850-1850/? I/PhoneApp﹕ trim memory
02-08 12:13:01.712     945-2088/? I/ActivityManager﹕ Process com.lge.p2p (pid 24102) has died
02-08 12:13:01.742     945-2041/? I/ActivityManager﹕ Process com.google.android.gms.wearable (pid 23833) has died
02-08 12:13:01.752    1850-1850/? I/PhoneApp﹕ onTrimMemory: 15
...
02-08 12:11:06.862  22936-22936/com.mycompany.ourapp W/IInputConnectionWrapper﹕ getTextBeforeCursor on inactive InputConnection
...
02-08 12:11:06.912  20890-20890/? D/Cliptray Manager﹕ isAvailable() UserHandle.myUserId() = 0, isOwner = true
02-08 12:11:06.912    1961-8134/? I/Cliptray Service﹕ Standard mode!! ClipTray is Supported!
02-08 12:11:06.912    1961-8134/? D/Cliptray Service﹕ isAvailable() mLastIsOwner = true
02-08 12:11:06.912    1961-8134/? I/Cliptray Service﹕ Owner!! ClipTray is Supported! mIsOwnerClipTray = true
02-08 12:11:06.912    1961-8134/? D/Cliptray Service﹕ ignore packageName : com.mycompany.ourapp
...
02-08 12:12:39.782  22936-22936/com.mycompany.ourapp I/Choreographer﹕ Skipped 35 frames!  The application may be doing too much work on its main thread.
...
02-08 12:13:02.622     945-2086/? I/WindowState﹕ WIN DEATH: Window{8dce4a3 u0 com.lge.launcher2/com.lge.launcher2.Launcher}
...
02-08 12:13:02.872     945-1922/? I/WindowState﹕ WIN DEATH: Window{393167d2 u0 InputMethod}
...
02-08 12:13:03.052    1979-1979/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.052    1961-1961/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.052    1850-1850/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.052    1850-1850/? D/QC_RIL_OEM_HOOK﹕ The connection to the service got disconnected unexpectedly!
02-08 12:13:03.072      945-945/? W/InputMethodManagerService﹕ Session failed to close due to remote exception
    android.os.DeadObjectException
            at android.os.BinderProxy.transactNative(Native Method)
            at android.os.BinderProxy.transact(Binder.java:496)
            at com.android.internal.view.IInputMethodSession$Stub$Proxy.finishSession(IInputMethodSession.java:305)
            at com.android.server.InputMethodManagerService.finishSessionLocked(InputMethodManagerService.java:1463)
            at com.android.server.InputMethodManagerService.clearClientSessionLocked(InputMethodManagerService.java:1454)
            at com.android.server.InputMethodManagerService.clearCurMethodLocked(InputMethodManagerService.java:1480)
            at com.android.server.InputMethodManagerService.onServiceDisconnected(InputMethodManagerService.java:1499)
            at android.app.LoadedApk$ServiceDispatcher.doDeath(LoadedApk.java:1391)
            at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1405)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at com.android.server.SystemServer.run(SystemServer.java:302)
            at com.android.server.SystemServer.main(SystemServer.java:203)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
...
02-08 12:13:03.132     945-2088/? I/ActivityManager﹕ Process com.google.process.gapps (pid 21317) has died
...
02-08 12:13:03.182    1405-1405/? D/LGKeyguardUnlockMethodController﹕ onTrustChanged with userId : 0 , getUserTrustIsManaged : false ,getUserHasTrust : false
...
02-08 12:13:03.452     362-1705/? V/AudioFlinger﹕ 22936 died, releasing its sessions
02-08 12:13:03.452     362-1705/? V/AudioFlinger﹕ pid 1850 @ 0
02-08 12:13:03.452     362-1705/? V/AudioFlinger﹕ pid 22936 @ 1
02-08 12:13:03.452     362-1705/? V/AudioFlinger﹕ removing entry for pid 22936 session 520
02-08 12:13:03.452     362-1705/? V/AudioFlinger﹕ purging stale effects
02-08 12:13:03.452     362-1705/? V/AudioFlinger﹕ remove track (4097) and delete from mixer
02-08 12:13:03.452     945-2086/? I/WindowState﹕ WIN DEATH: Window{3eafa2d1 u0 com.mycompany.ourapp/com.mycompany.ourapp.MainActivity}

可能部分负责的内存泄漏:https://code.google.com/p/android/issues/detail?id=79729

问题

导致应用程序以这种方式崩溃的原因是什么?这是记忆问题吗?我在这里复制的日志输出中的任何内容是相关的吗?

还有其他人有这个问题并解决了吗? Android 5.0.x / 1.x内存泄漏错误是否负责?

我希望我可以更具体,但代码是专有的,问题不是(或尚未)本地化到任何一个特定的代码示例。如果需要有关特定问题的更多信息,请询问。

更新

我注意到日志中有一堆Choreographer消息,说它做了太多工作,但是它们是相对较小的帧跳过(~35帧),最后一条消息在应用程序崩溃前整整20秒发生

更新2-10-16

我们现在正在尝试重复使用canvas对象,以防它们没有被垃圾回收,我们也在使用System.gc()调用onTrimMemory时调用TRIM_MEMORY_RUNNING_LOW。这似乎在一定程度上减少了崩溃,但仍然经常足以令人担忧。最重要的是,我想了解为什么它似乎随机消耗太多内存和崩溃。我已将onTrimMemory行添加到下面的日志输出中,这表示它在100 ms的范围内从低到严重。如果仅在实际执行内存密集型操作时发生这种情况,那么这有意义,但有时在用户进程完成后很久就会发生。

3 个答案:

答案 0 :(得分:2)

  

您正在处理大型位图并在运行时加载所有这些位图   时间。您必须通过加载非常仔细地处理大位图   您需要的大小不是整个位图,而是一次   缩放。

巨大的JavaScript导致此

鉴于您正在使用有限的内存,理想情况下您只想在内存中加载较低分辨率的版本。较低分辨率版本应与显示它的UI组件的大小相匹配。具有更高分辨率的图像不会提供任何明显的好处,但仍会占用宝贵的内存,并且由于额外的动态扩展而产生额外的性能开销。

请检查 Managing Bitmap Memory

你正在使用大量的画布,这就是为什么会出现这个问题。

答案 1 :(得分:2)

这曾经发生在我身上,即使我在应用程序清单中使用了大堆属性,并且在完成使用后将所有变量重置为null时停止发生。

我不知道你的代码,但我建议你重复使用相同的变量,并确保你在每次操作后完成清理,因为在内存中保留大量未使用的文件并不好。

答案 2 :(得分:2)

将头发拉到这里,尝试在Fire TV Stick上运行CrossWalk中运行的基于HTML Canvas的应用程序。该应用程序运行正常,然后在使用此错误30分钟后崩溃。我能够解决它,但我的用例非常具体,无论哪种方式,它可以帮助以后出现在这里的人。

TL; DR:减少加载进出GPU的纹理的大小。

我有一个运行PixiJS的全屏画布元素,基本上用作幻灯片。问题来自单一幻灯片类型,其中具有透明度的大图像将在固定背景上生成动画。在Chrome的时间轴功能中记录CPU / GPU使用情况后,我可以看到纹理一直在加载进出GPU,以实现这种效果。最终,我能够通过从画布中完全删除背景图像元素并将其显示在画布后面的div中来解决问题。影响是相同的,但性能得到了显着改善,之后这个问题就消失了。