2014-03-26 34 views
2

任何人都可以解釋下面的logcat消息:Android的Dalvik虛擬機的logcat

D/dalvikvm(4440): GC_EXTERNAL_ALLOC freed 338K, 47% free 6427K/11911K, external 20418K/22446K, paused 53ms 
E/dalvikvm-heap(4440): 2519424-byte external allocation too large for this process. 
D/dalvikvm(4440): GC_FOR_MALLOC freed <1K, 47% free 6427K/11911K, external 20398K/22446K, paused 40ms 
E/GraphicsJNI(4440): VM won't let us allocate 2519424 bytes 
+0

哪個版本的Android,這是來自哪裏? – fadden

+0

對於2.2版 –

+1

寫了一篇好博客。您可以參考:https://sites.google.com/site/pyximanew/blog/androidunderstandingddmslogcatmemoryoutputmessages –

回答

3

在老版本的Android,原生框架代碼的某些位會告訴VM有關本機的分配。這種「外部分配」機制是一種醜陋的黑客攻擊,因此本地分配會導致Dalvik虛擬機執行垃圾收集。

的基本問題是Java語言的位圖對象使用本機內存爲像素存儲。由於託管堆對象很小,並且本機堆對象很大,因此您可以分配大量位圖而不會導致GC。這導致應用程序膨脹並且系統變慢。

所以, 「外部分配」 進行了介紹。每當在本地堆上分配一個位圖的像素存儲時,就會從託管堆中減去相同數量的內存。這個想法是,如果你的堆堆滿了沒有長參考的位圖,那麼你的堆空間就會耗盡,並且GC將會啓動。 (不幸的是,GC不能真正釋放本地存儲 - 你需要運行一個終結器來完成這個任務,並且終結器在GC完成後在一個單獨的過程中運行。一段時間,本地對象也持有到一些額外的managed-heap對象,所以你必須使用GC + finalize + GC來實際清理所有東西。)

關於外部分配​​的我最喜歡的部分是API是一個簡單的「增加N」 /「減少N」,這意味着沒有辦法將本地堆與託管堆對象相關聯,或者檢查是否存在泄漏。因爲關於Bitmap的所有信息都保存在本地對象中,所以您甚至無法猜測需要多少本機存儲,因此無法查看hprof轉儲並找出Bitmap實際使用的內存量。

在Android 3.0的(「蜂窩」)中的像素存儲被移動到託管堆,併除去外部分配機制。

那麼,是什麼在你的問題的日誌信息的意思是:一些代碼,可能是位圖,想分配本機堆的2.5MB,但是這將超出虛擬機的外部分配堆限制。你需要弄清楚什麼是20MB的外部分配存儲,並釋放一些。

,以獲取有關外部分配的信息的唯一途徑是通過觀看事件日誌。幾年前,我一起扔了一個劇本(gclog.py - 在AOSP達爾維克/工具一段時間)。我不知道它是否仍然有用。我會談談如何在this old thread中使用它。

+0

感謝您的回覆。你的帖子真的很有幫助。現在我已經更好地理解託管堆和本機堆。我已經解決了這個問題,只需調用bitmap.recycle(),當位圖不再被使用(或不再被引用)時。 –