2011-06-22 18 views
21

我有一個ListView,我期望它在活動結束時從內存中清除。但是,它似乎正在泄漏。當我檢查了內存轉儲,並得到pathToGCListView我得到以下,由於AudioManager引起的Android上下文內存泄漏列表視圖

Class Name               | Shallow Heap | Retained Heap 
android.widget.ExpandableListView @ 0x4063e560      |   768 |  39,904 
|- list, mList com.hitpost.TeamChooser @ 0x405f92e8     |   176 |   1,648 
| '- mOuterContext android.app.ContextImpl @ 0x40657368   |   160 |   304 
|  '- mContext android.media.AudioManager @ 0x40662600   |   40 |   168 
|  '- this$0 android.media.AudioManager$1 @ 0x406626b0 Unknown|   24 |   24 

我看到同樣的情況下泄露了很多我的ListView's的。訣竅是,我沒有在我的應用程序的任何地方使用AudioManager,根本沒有聲音來自應用程序。請幫忙,這讓我瘋狂。顯然試圖找出爲什麼會發生這種情況,根本問題是什麼?

+0

你使用任何靜力學? – mibollma

+0

嗯,是有靜態變量,只是從一個具有ListView的活動中刪除所有這些變量。但是同樣的情況仍然在泄漏。 – Leo

+0

它與ListView以及與AudioManager無關。你在用AudioManager做什麼? – cyngus

回答

-4

如果您的應用程序崩潰了內存泄漏,那麼您可以使用try-catch(java.lang.outofmemory)來避免此崩潰。事實是GC由JVM本身調用,因此程序員無法控制這一點。您可以將應用程序安裝在SD卡中,在這種情況下,將使用SD卡存儲器。內存泄漏不會發生。

只要進入你的清單文件,必須有版本號。版本名稱,還必須有「安裝位置」,使其成爲「preferExternal」。

+0

我不認爲這回答了我的問題。 – Sameer

+0

@santanu,_您可以將您的應用程序安裝在SD卡中,在這種情況下,將使用SD卡存儲器。內存泄漏將不會發生。我勒個去? – 2012-03-17 23:16:40

+1

@haibison內存泄漏是[不同](http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html)。這是關於RAM被不必要地使用,並且與SD卡無關。 – zapl

5

在您的代碼中有幾處引用AudioManager,您不會主動創建。例如。每個可點擊的View可能有一個可以播放onClick聲音[source]。我想這是鏈接。

如果您在設置中停用了點擊聲音,代碼看起來像不會創建對AudioManager的引用。你可以嘗試,並檢查是否仍然有泄漏。

您泄漏的原因可能是您在ListView(Adapter?)代碼中持有一些View對象。如果你讓他們身邊,那麼你可能有一個View有一個AudioManagerreference,並且保持一個Context參考)

+0

因爲我認爲大多數應用程序在那裏我有同樣的問題。 –

+2

我不認爲答案應該圍繞上下文進行。 'AudioManager'是一個單例類和一個系統類。垃圾收集器知道這一點,並相應地執行適當的收集。您只需在轉儲內存之前進行GC調用即可。 – redDragonzz

0

我在應用程序中發現的最常見原因是由於通過XML文件初始化某些組件。當你這樣做,Activity Context被注入,但有時你只需要一個ApplicationContext。對於Android中的Web View,這種技術對我有很大的幫助。

0

我想分享我的經驗,關於同一個問題,我保留了一些活動在默認情況下堆棧,並沒有完成他們。

對於這些活動,我得到了與hprof報告中提到的相同的內容。

一旦我完成不再使用活動,上述參考沒有來。只需完成不再需要的活動,就可以解決此問題。

1

在這種情況下,您可以使用應用程序上下文來避免泄漏。我不知道爲什麼,但是當我開始使用應用程序上下文時,問題消失了。

7

完全不相關OP的泄漏,但對於誰在這裏是因爲AudioManager造成漏人:

如果您看到此泄漏,因爲你正在使用VideoView,可能是因爲這個錯誤:https://code.google.com/p/android/issues/detail?id=152173

如果視頻被加載,VideoView從不發佈AudioManager。

解決方法是,如鏈接中所述,使用ApplicationContext手動創建VideoView。

編輯:此解決方案將工作,直到...如果視頻解碼器說視頻有編碼問題。 VideoView嘗試使用應用程序上下文彈出AlertDialog。發生崩潰。

我唯一能想到的工作就是繼續使用活動上下文創建視頻視圖,並在activity.onDestroy中使用反射將AudioManager的mContext設置爲應用程序上下文。

注意:必須使用activity.getSystemService(Context.AUDIO_SERVICE)而不是activity.getApplicationContext.getSystemService(Context.AUDIO_SERVICE)來獲取AudioManager,因爲AudioManager是Context的成員變量(您將獲得AudioManager的錯誤實例if你從應用程序上下文中獲得它)。

最後,您可能想知道爲什麼成員變量(AudioManager)阻止垃圾收集類(Activity)。從內存分析器中可以看出,AudioManager屬於本地堆棧。所以AudioManager不能正常清理本身。

0

這是一個複製的問題一個非常基本的活動(在Android 4.0.3至少)

public class MainActivity extends Activity { 

    int image[]; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // setContentView(R.layout.activity_main); 
     image = new int[1000 * 1500 * 4]; 
    } 
} 

正如你可以看到有沒有與活動相關意見或Layots,也是我將「靜音」系統聲音設置中的配置文件,並關閉「振動觸摸」。

現在,幾(5-7取決於您的heapSize)重新啓動後,此活動會嘗試創建新數組時生成java.lang.OutOfMemoryError。

07-27 19:54:10.160 22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 25ms 
07-27 19:54:10.190 22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed 23449K, 43% free 32591K/56391K, paused 30ms 
07-27 19:54:10.260 22542-22543/? D/dalvikvm﹕ GC_CONCURRENT freed 0K, 1% free 56029K/56391K, paused 3ms+3ms 
07-27 19:54:11.850 22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 20ms 
07-27 19:54:11.880 22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed <1K, 1% free 56040K/56391K, paused 29ms 
... Out of memory on a 24000016-byte allocation. 

轉儲.hprof我還看到2個活動,其中一個是由AudioManager持有。

調用「更新堆」,然後收集,在Android設備監控垃圾確實從內存中刪除的活動,也就是在這個過程

07-27 19:44:23.150  85-85/? I/DEBUG﹕ #06 pc 000382cc /system/lib/libdvm.so (dvmCollectGarbageInternal(GcSpec const*)+1204) 

的logcat的狀態我也試圖構建發佈版本的apk和它的行爲相同。所以它不是調試器持有的參考。

在我看來,這是Android中的一個錯誤。解決方法是顯式調用活動的OnStop()或onFinish()中的image = null。這當然不方便。