我在Android 5.x Camera2 API中发现内存泄漏,我也reported。问题是当您使用具有在LEGACY
模式下实施的Camera2 API的Android Lollipop设备时。在此类设备上,调用context.getSystemService(Context.CAMERA_SERVICE)
会导致context
被保留,因此无法进行垃圾回收。
如果此context
是您多次启动的活动,则最终可能会挂起对您的活动的几十个实例的引用,这些实例从不被垃圾回收。
这个问题似乎只发生在以LEGACY
模式实现Camera2 API的Lollipop设备上(例如HTC One M8,三星Galaxy S4),而在三星Galaxy S6上却没有发生,它实现了{2}中的Camera2 API {1}}模式。
为了证明这个问题,我创建了一个small demo app。该应用程序包含两个活动:首先包含一个调用第二个活动的按钮。第二个活动获取FULL
并查询第一个后向摄像头的Camera2 API支持级别,并将结果返回给第一个活动。如果您在CameraManager
模式下实施Camera2 API的设备上运行应用程序,在点击按钮98次,导致GC然后转储HPROF后,您将看到LEGACY
的98个实时实例,如此{{ 3}}
如果您在Main2Activity
模式下实施Camera2 API的设备上执行相同操作,您将看到FULL
的0个实时实例,如此http://www.pohrani.com/f/1H/gs/4EFlHKoj/sgs4.png
有没有办法解决这个漏洞?
有人可能会问为什么我这样做?在我们公司,我们正在开发http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png以及着名的barcode and OCR scanning solutions。因此,我们有扫描活动来控制相机和扫描过程。在启动时,活动会检查设备是否支持Main2Activity
或FULL
模式下的Camera2 API并尝试使用它以获得更好的性能,而如果Camera2 API处于LIMITED
模式,那么我们更喜欢使用旧相机API使用相机管理,就像我们在Lollipop前设备上所做的那样。
由于提到的内存泄漏,每当将SDK集成到其应用程序中的客户端启动扫描活动,执行扫描并获得结果时,由于该错误,一个扫描活动实例将被泄露。如果客户端扫描很多,这可能会占用超过20 MB的内存 - 这是一个严重的问题!
因此,如果有人知道如何为此问题制定解决方法,我将永远感激不尽!
答案 0 :(得分:6)
有没有办法解决这个漏洞?
您可以在getSystemService()
单身人士上致电Application
。所以,而不是:
getSystemService(CAMERA_SERVICE)
你会用:
getApplicationContext().getSystemService(CAMERA_SERVICE)
如果您的评估是正确的,那么这将导致这些额外的引用属于现有的Application
单例,这在您的过程中始终存在。它是有效的"预先泄露的",你不能通过更多的参考来泄漏它。
答案 1 :(得分:1)
这是在L MR1中修复的Android错误。
基本上,CameraManager保留了对其创建的上下文的引用,然后连接到相机服务。此连接使摄像机管理器实例无限期地保持活动状态,因此也使Context保持无限期。
这已在L MR1中修复,以便在不再引用时正确地允许回收CameraManager对象。