【问题标题】:How to avoid memory leak in context.getSystemService(Context.CAMERA_SERVICE)?如何避免 context.getSystemService(Context.CAMERA_SERVICE) 中的内存泄漏?
【发布时间】:2015-11-03 18:45:29
【问题描述】:

我在 Android 5.x Camera2 API 中发现了内存泄漏,我也发现了 reported。问题是当您使用在LEGACY 模式下实现了 Camera2 API 的 Android Lollipop 设备时。在此类设备上,调用 context.getSystemService(Context.CAMERA_SERVICE) 会导致 context 被保留,以便不会被垃圾回收。

如果这个context 是您多次启动的活动,您最终可能会挂起对几十个从未被垃圾回收的活动实例的引用。

这个问题似乎只发生在在 LEGACY 模式下实现了 Camera2 API 的棒棒糖设备上(例如 HTC One M8、三星 Galaxy S4),而在 FULL 中实现 Camera2 API 的三星 Galaxy S6 上不会发生此问题模式。

为了演示这个问题,我创建了一个small demo app。该应用程序包含两个活动:第一个包含一个调用第二个活动的按钮。第二个活动获取CameraManager 并查询Camera2 API 对第一个后置摄像头的支持级别,并将结果返回给第一个活动。如果你在LEGACY模式下在实现Camera2 API的设备上运行应用程序,在点击按钮98次后,导致GC然后转储HPROF,你将看到Main2Activity的98个实时实例,就像这样http://www.pohrani.com/f/1H/gs/4EFlHKoj/sgs4.png

如果您在以FULL 模式实现 Camera2 API 的设备上执行相同操作,您将看到 Main2Activity 的 0 个实时实例,例如 http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png

有没有办法解决这个泄漏?

有人可能会问我为什么要这样做?在我们公司,我们正在开发barcode and OCR scanning solutions 和著名的PhotoMath app。所以我们有一个扫描活动来控制相机和扫描过程。启动时,活动检查设备是否支持 FULLLIMITED 模式下的 Camera2 API,并尝试使用它以获得更好的性能,而如果 Camera2 API 处于 LEGACY 模式,那么我们更喜欢使用旧相机使用相机管理API,就像我们在棒棒糖之前的设备上所做的那样。

由于上述内存泄漏,每当将我们的 SDK 集成到其应用程序中的客户端启动扫描活动、执行扫描并获取结果时,都会由于该错误而泄漏一个扫描活动实例。如果客户端扫描很多,这可能会占用超过 20 MB 的内存 - 一个严重的问题!

因此,如果有人知道如何解决此问题,我将永远感激不尽!

【问题讨论】:

    标签: android memory-leaks garbage-collection android-camera


    【解决方案1】:

    有没有办法解决这个泄漏?

    您可以在 Application 单例上调用 getSystemService()。所以,而不是:

    getSystemService(CAMERA_SERVICE)
    

    你会使用:

    getApplicationContext().getSystemService(CAMERA_SERVICE)
    

    如果您的评估是正确的,那么这将导致这些附加引用指向现有的 Application 单例,它始终在您的流程中。它实际上是“预泄漏”的,您不能通过对它的更多引用来进一步泄漏它。

    【讨论】:

    • 我打算发布相同的答案 :)
    • 好主意!像魅力一样工作:-)
    【解决方案2】:

    这是在 L MR1 中修复的 Android 错误。

    基本上,CameraManager 保留了对其创建时使用的上下文的引用,然后连接到相机服务。这种连接使相机管理器实例无限期地保持活动状态,因此也使 Context 无限期地保持活动状态。

    L MR1 中已修复此问题,以便在不再引用时正确允许回收 CameraManager 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      • 2018-04-08
      相关资源
      最近更新 更多