導航:首頁 > 解決方法 > 內存泄漏的原因及解決方法

內存泄漏的原因及解決方法

發布時間:2023-04-15 06:03:01

❶ 內存溢出和內存泄漏的區別產生原因以及解決方案。

內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。
內存泄露 memory leak,是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光。
memory leak會最終會導致out of memory!

產生的原因:

1.內存中載入的數據量過於龐大,如一次從資料庫取出過多數據;

2.集合類中有對對象的引用,使用鍵晌完後未清空,使得JVM不能回基慧收;

3.代碼中存在死循環或循環產生過多重復的對象實體;

4.使用的第三方軟體中的BUG;

5.啟動參數內存值設定的過小

解決方案:

1)處理一些IO流的數據傳輸時,盡量結束時候把IO流關掉

2)處理下載照片時候,使用BitmapFactory.options。設置insameplesize()方法壓縮圖片減少資源的佔用;圖片的壓縮問題下面會寫一個專門專題來講;

3)還可以通過降低照片像素的方法,從而降低佔用的內存

4)資源的回收:Bitmap.recycle()bitmap=null;

5)盡量使用全局的變數,少new新的對象

❷ Android技術分享|Android 中部分內存泄漏示例及解決方案

內存泄漏:

舉例:

請注意以下的例子是虛構的

內存抖動

源自Android文檔中的 Memory churn 一詞,中文翻譯為內存抖動。

指快速頻繁的創建對象從而產生的性能問題。

引用Android文檔原文:

Java內存泄漏的根本原因是 長生命周期 的對象持有 短生命周期 對象的引用就很可能發生內存泄漏。

盡管短生命周期對象已經不再需要,但因為長生命周期依舊持有它的引用,故不能被回收而導致內存泄漏。

靜態集合類引起的內存泄漏


如果僅僅釋放引用本身(tO = null), ArrayList 依然在引用該對象,GC無法回收。

監聽器

在Java應用中,通常會用到很多監聽器,一般通過 addXXXXListener() 實現。但釋放對象時通常會忘記刪除監聽器,從而增加內存泄漏的風險。

各種連接

如資料庫連接、網路連接(Socket)和I/O連接。忘記顯式調用 close() 方法引起的內存泄漏。

內部類和外部模塊的引用

內部類的引用是很容易被遺忘的一種,一旦沒有釋放可能會導致一系列後續對象無法釋放。此外還要小心外部模塊不經意的引用,內部類是否提供相應的操作去除外部引用。

單例模式

由於單例的靜態特性,使其生命周期與應用的生命周期一樣長,一旦使用不恰當極易造成內存泄漏。如果單利持有外部引用,需要注意提供釋放方式,否則當外部對象無法被正常回收時,會進而導致內存泄漏。

集合類泄漏

如集合的使用范圍超過邏輯代碼的范圍,需要格外注意刪除機制是否完善可靠。比如裂寬由靜態屬性 static 指向的集合。

單利泄漏

以下為簡單邏輯代碼,只為舉例說明內存泄漏問題,不保證單利模式的可靠性。


AppManager 創建時需要傳入一個 Context ,這個 Context 的生命周期長短至關重要。

1. 如果傳入的是 Application 的 Context ,因為 Application 的生命周期等同於應用的生命周期,所以沒有任何問山源清題。

2. 如果傳入的是 Activity 的 Context ,則需要考慮這個 Activity 是否在整個生命周期都不會被回收了,如果不是,則會造成內存泄漏。

非靜態內部類創建靜態實例造成的內存泄漏


應該將該內部類單獨封裝為一個單例來使用。

匿名內部類/非同步線程


Runnable都使用了匿名內部類,將持有MyActivity的引用。如果任務在Activity銷毀前未完成,將導致Activity的內存無法被回收,從而造成內存泄漏。

解決方法:將Runnable獨立逗前出來或使用靜態內部類,可以避免因持有外部對象導致的內存泄漏。

Handler造成的內存泄漏


Handler屬於TLS(Thread Local Storage)變數,生命周期與Activity是不一致的,容易導致持有的對象無法正確被釋放

當Android應用程序啟動時,該應用程序的主線程會自動創建一個Looper對象和與之關聯的MessageQueue。

當主線程中實例化一個Handler對象後,它就會自動與主線程Looper的MessageQueue關聯起來。所有發送到MessageQueue的Messag都會持有Handler的引用,所以Looper會據此回調Handle的handleMessage()方法來處理消息。只要MessageQueue中有未處理的Message,Looper就會不斷的從中取出並交給Handler處理。

另外,主線程的Looper對象會伴隨該應用程序的整個生命周期。

在Java中,非靜態內部類和匿名類內部類都會潛在持有它們所屬的外部類的引用,但是靜態內部類卻不會。

當該 Activity 被 finish() 掉時,延遲執行任務的 Message 還會繼續存在於主線程中,它持有該 Activity 的 Handler 引用,所以此時 finish() 掉的 Activity 就不會被回收了從而造成內存泄漏(因 Handler 為非靜態內部類,它會持有外部類的引用,在這里就是指 SampleActivity)。


避免不必要的靜態成員變數

對於BroadcastReceiver、ContentObserver、File、Cursor、Stream、Bitmap等資源的使用,應在Activity銷毀前及時關閉或注銷。

不使用WebView對象時,應調用`destroy()`方法銷毀。

❸ 內存泄漏、內存溢出

有一種情況下,oom可以通過try catch掉, 如果try catch語句中,聲明了很大的對象導致OOM,並且確認OOM是由try語句中的對象聲明導致的,那麼在catch語句中,可以釋放掉這些對象,解決OOM問題,繼續執行剩餘的語句。

上述做法不建議,畢竟catch掉異常,而不是想著解決OOM

Java中管理內存除了catch oom之外還有很多有效的方法,如SoftReference、WeakReference、硬碟緩存等。
在JVM用光內存之前,會多次觸發GC,這些GC會降低程序運行的效率。
如果OOM原因不是try語句中對象(比如內存泄漏),那麼在catch語句中會繼續拋出OOM

在此可以了解一下內培敗存泄漏和內存溢出的區別:

常發性、偶發性、一次性、隱式

怎樣解決內存泄漏: 泄漏是因為持有了activity引用導致無法被銷毀,一配並顫是及時取消引用蔽掘,二是讓引用多待一會,但是該GC的時候就銷毀

❹ 內存溢出和內存泄漏

內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。

內存泄露 memory leak,是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光。

memory leak會最終會導致out of memory!

一,常見的內存溢出情況:
1,載入圖片過大,超出所申請的內存
解決方法:

(1)對圖片進行壓縮處理(不推薦,圖片多起來,你再怎麼壓縮也是要耗很大的內存)

(2)使用第三方載入圖片框架(推薦,開源,省時又省事)Glide ,Picasso ,Fresco等

(3)減少Bitmap對象的引用,並及時的回收

2,對象引用沒及時回收,導致堆積,超出所申請的內存
解決方法:

(1)動態回收內存

(2)對像引用採用軟引用(方便內能夠對此進行回收)

(3)對象復用,存在的對象不要重復多次new它,應該循環利用

(4)注意對象復用的生命周期(static和程序進程一樣長)

(5)單例模式的合理使用,單例模式避免重復創建對象,但也注意他的生命周期和程序進程一樣長容易因為持有的對象沒有正常回收導致內存泄漏

(6)監聽器不使用時及時注銷

(7)盡量減少抽象對象的使用

3,頁面持有內存,沒有及時回收
(1)Activity,fragment頁面:

(2)webview頁面

4,無用服務後台持續運作,佔用過多內存
(1)用完及時關閉

二,常見的內存泄漏情況:
1,Handler 引發內存泄漏
(1)handler發送的Message未被處理,那麼該Message及發送它的Handler對象都會被線程一直持有,由於Handler屬於TLS(Thread Local Storage)變數,生命周期和Activity是不一致的。如果Handler是我們的Activity類的非靜態內部類,Handler就會持有Acitvity的強引用,此時該Activity退出時無法進行內存回收,造成內存泄漏。

解決方法:

將Handler聲明為靜態內部類和軟引用,這樣它就不會持有外部類的引用了,Handler的生命周期就與Activity無關了。聲明時context採用Application的Context,銷毀Acitvity時處理掉隊列中的消息。

2,單例模式引發內存泄漏
(1)單例模式的靜態屬性,使它的生命周期和應用一樣長,如果讓單例引用Activity的強引用,Activity無法gc,就會導致內存泄漏。

解決方法:

所以在創建單例時,構造函數里對Activity 的context引用換成 ApplicationContext

3,匿名內部類引起內存泄漏
(1)activity ,fragment 或者view中使用匿名類,匿名類對象會持有Activity,Fragment,View的引用,如果引用傳到非同步線程中,非同步線程和Activityt生命周期不一致的時候,就會造成Activity的泄漏。

解決方法:能直接聲明內部類引用就減少匿名內部類的引用。盡量不把匿名內部類用到非同步線程中去

4,WebView 引起的內存泄漏
(1)webview解析網頁時會申請Natvie堆內存用於保存頁面元素,當頁面較復雜時,會有很大的內存佔用。如果包含圖片,內存佔用會更嚴重,並且打開新頁面時,為了能快速回退,之前頁面內存也不會釋放。或者是退出Activity頁面時,webview還在處理網路數據,持有Activity的引用時會導致Activity不能被Gc也會造成內存泄漏。

解決方法:

webview採用動態添加,onDestroy時移除,和銷毀webview。

5,集合引發的內存泄漏
(1)把對象的引用加入集合容器中,當我們不再需要該對象時,並沒有把它的引用從集合中清理掉,當集合中的內容過大的時候,並且是static的時候就造成了內存泄漏。

解決方法:

在onDestory中清空;

6,其他引發內存泄漏
(1)構造Adapter時,沒有使用緩存的convertView

(2)Bitmap在不使用的時候沒有使用recycle()釋放內存

(3)線程未終止造成內存泄漏

(4)對象的注冊與反注冊沒有成對出現造成的內存泄漏;比如注冊廣播接收器,注冊觀察者等

(5)不要在執行頻率很高的方法或者循環中創建對象。

本文整理自以下兩篇文章
原文鏈接: https://blog.csdn.net/lililijunwhy/article/details/87966337
原文鏈接: https://blog.csdn.net/sasafeng/article/details/8559992

❺ 內存溢出的解決方法

內存溢出是指應用系統中存在無法回收的內存或使用的跡桐內存過多,最終使得程序運行要用到的內存大於虛擬機能提供的最大內存。
內存中載入的數據量過於龐大,如一次從資料庫取出過多數如州賣據;集合類中有對對象的引用,使用完後未清空,使得JVM不能回渣逗收;代碼中存在死循環或循環產生過多重復的對象實體;使用的第三方軟體中的BUG;啟動參數內存值設定的過小;
檢查對資料庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,資料庫中數據較少,不容易出問題,上線後,資料庫中數據多了,一次查詢就有可能引起內存溢出。因此對於資料庫查詢盡量採用分頁的方式查詢。
檢查代碼中是否有死循環或遞歸調用。

❻ 內存泄漏是什麼

什麼是內存泄漏?
一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的工內存塊的大小可以在程序運行期決定),使用完後必須顯示釋放的內存。應用程序一般使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完後,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了。
請解釋一下「內存泄漏」,這個問題會有什麼影響
申請了內存不釋放就是內存泄露 比如. void GetMemory(int len) { int *p =new int[len]; } p申請了內存,但是函數返回了,沒有指針的首地址傳出來,不能釋放了
內存泄漏是什麼意思?簡單說說就行了。
簡單說 內存中的某一塊正在被其他程序使用 這時如果再有其他程序試圖使用這塊內存 就會發生內存泄露
內存泄漏是指_______
選D項,實際上是堆內存分配後,至最終都沒有被回收,始終被佔用

最典型的例子是使用new分配內存,在整個程序中一直沒有使用delete銷毀,這就造成了使用new分配的那部分堆內存始終被佔用(沒有被釋放)
內存泄露有一點想不明白,到底什麼樣才算內存泄漏
工具-選項-高級-更新-Firefox的對號去掉就行了。事實上3.0以後的版本帆姿配對內存的管理更好了,內存泄露已經很少見了,但對於內存的最小值要求貌似更高一些,我曾經在256內存的電腦上使用3.6沒什麼問題,當然,由於cpu不足引起的flash響應慢就不算了。再小的內存就沒用過了,不知道什麼樣。
什麼是內存溢出與內存泄露,幾種常見導致內存泄露的
內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。

內存泄露 memory leak,是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光。

memory leak會最終會導致out of memory!

內存溢出就是你要求分配的內存超出了系統能給你的,系統不能滿足需求,於是產生溢出。

內存泄漏是指你向系統申請分配內存進行使用(new),可是使用完了以後卻不歸還(delete),結果你申請到的那塊內存你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程序。一個盤子用盡各態指種方法只能裝4個果子,你裝了5個,結果掉倒地上不能吃了。這就是溢出!比方說棧,棧滿時再做進棧必定產生空間溢出,叫上溢,棧空時再做退棧也產生空間溢出,稱為下溢。就是分配的內存不足以放下數據項序列,稱為內存溢出.

以發生的方式來分類,內存泄漏可以分為4類:

1. 常發性內存泄漏。發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏。

2. 偶發性內存泄漏。發生內存泄漏的代碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測內存泄漏至關重要。

3. 一次性內存泄漏。發生內存泄漏的代碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏。比如,在類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,所以內存泄漏只會發生一次。

4. 隱式內存泄漏。程序在運行過程中不停的分配內存,但是直到結束的時候才釋放內存。嚴格的說這里並沒有發生內存泄漏,因為最終程序釋放了所有申請的內存。但是對於一個伺服器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所有內存。所以,我們稱這類內存泄漏為隱式內存泄漏。

從用戶使用程序的角度來看,內存泄漏本身不會產生什麼危害,作為一般的用戶,根本感覺不到內存泄漏的存在。真正有危害的是內存泄漏的堆積,這會最終消耗盡系統所有的內存。從這個角度來說,一次性內存泄漏並沒有什麼危害,因為它不會堆積,而隱式內存泄漏危害性則非常大,因為較之於冊洞常發性和偶發性內存泄漏它更難被檢測到

內存溢出的原因以及解決方法

引起內存溢出的原因有很多種,我列舉一下常見的有以下幾種:

1.內存中載入的數據量過於龐大,如一次從資料庫取出過多數據;

2. *** 類中有對對象的引用,使用完後未清空,使得JVM不能回收;

3.代碼中存在死循環或循環產生過多重復的對象實體;

4.使用的第三方軟體中的BUG;

5.啟動參數內存值設定的過小

內存溢出的解決方案:

第一步,修改JVM啟動參數,直接增加內存。(-Xms,-Xmx參數一定不要忘記加。)

第二步,檢查錯誤日誌,查看逗OutOfMemory地錯誤前是否有其它異常或錯誤。

第三步,對代碼進行走查和分析,找出可能發生內存溢出的位置。

重點排查以下幾點:

1.檢查對資料庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,資料庫中數據較少,不容易出問題,上線後,資料庫中數據多了,一次查詢就有可能引起內存溢出。因此對於資料庫查詢盡量採用分頁的方式查......>>
java內存泄露,是什麼意思
內存泄露是指你申請了內存空間但是沒有控制釋放,然後那一塊內存就被荒廢了,你自己不用了,別人也用了不了,結果內存就被你占滿了
什麼是內在泄露...內存泄露了會有什麼後果..??
內存泄漏是主內存分配了部分內存後而沒有釋放,逐漸耗盡內存資源,導致系統崩潰。它的後果甚至是會影響到以後內存的正常運行或使用內存損壞~~~ 它主要是指程序中間動態分配了內存,但是在程序結束時沒有釋放這部分內存,從而造成那一部分內存不可用的情況,重起計算機可以解決,但是也有可能再次發生內存泄露,內存泄露和硬體沒有關系,它是由軟體引起的。而在一般情況下無法輕易被發現的其實它也是輕易不是出現的,它就好象你坐在一個升降機里所在是13樓而你還按下13樓的按扭一樣,內存泄露只會在這樣的情況下出現的,不過內存泄露或者內存泄漏說還是會比一個人站在13樓還按要去13樓的按扭這樣的情況要多的多,因為有時內存泄漏會時常發生在用戶使用某些較大且較復雜的程序中~~~~處理的辦法也只有使用一些軟體來測試內存有沒有這樣泄露的問題了~~~~~不過要是隱性式的內存泄漏就不太好辦了~~~要根據當前發生一些問題或是一些操作來判斷是否發生內存泄漏的問題
c++中中內存泄露有什麼危害?
從用戶使用程序的角度來看,內存泄漏本身不會產生什麼危害。作為一般的用戶,根本感覺不到內存泄漏的存在。真正有危害的是內存泄漏的堆積,這會最終消耗盡系統所有的內存。從這個角度來說,一次性內存泄漏並沒有什麼危害,因為它不會堆積。而隱式內存泄漏危害性則非常大,因為較之於常發性和偶發性內存泄礌它更難被檢測到。存在內存泄漏問題的程序除了會佔用更多的內存外,還會使程序的性能急劇下降。對於伺服器而言,如果出現這種情況,即使系統不崩潰,也會嚴重影響使用。

不過還有一點,如果你的程序內存泄露正好寫到了系統使用的內存或者其他程序使用的內存地址,那麼就會導致系統異常或者程序崩潰
什麼是內存泄漏 如何避免
內存泄漏的定義: 對象不再被應用程序使用,但是垃圾回收器卻不能移除它們,因為它們正在被引用。

如何阻止內存泄漏?

以下是一些阻止內存泄漏的快速動手技巧。

(1)注意 *** 類,例如HashMap,ArrayList,等等。因為它們是內存泄漏經常發生的地方。當它們被聲明為靜態時,它們的生命周期就同應用程序的生命周期一般長。

(2)注意事件監聽器和回調,如果一個監聽器已經注冊,但是當這個類不再被使用時卻未被注銷,就會發生內存泄漏。

(3)「如果一個類管理它自己的內存,程序員應該對內存泄漏保持警惕。」[1] 很多時候當一個對象的成員變數指向其他對象時,不再使用時需要被置為null。

希望這個回答對你有幫助

❼ skynet網路層內存泄漏

Skynet是一種旨在輕量級並為多人游戲提供服務的網路框架。在使用Skynet的過程中,可能會遇到內存泄漏的問題。下面是一些可能導致Skynet網路層內存泄漏的原因和解決方法:

1. 長時間運行的服務
一些服務可能會持續很長時間,如果這些服務創建了一些內容,則這些內容會一直佔用內存。因此,需要在服務完成後清理它們分配的內存。可以通過在服務初始化時分配一個內存池來解決這個問題,在服務完成時釋放內存池。

2. 沒有正確處理消息
Skynet使用非同步消息傳遞來處理協作操作,如果服務沒有正確處理消息,則內存可能會泄漏。在處理消息時,需要記住釋放不再使用的內存,例如在發送消息之前動態分配內存,或在調用回調函數之後動態分配內存。

3. 協作操作泄漏
在使用Skynet的時候,可能會發生一些協作操作,例如發送消息、注冊timer等等,如果沒有正確處理這些事件,可能會導致內存泄漏。因此,在使用Skynet時,需要確保正確處理這些協作操作,並在用完之後及時釋放相關內存斗皮亮。

4. 跨服務的共享內存
在Skynet中,有時需要在多個服務之間共享內存。如果這些共享內存沒握爛有正確管理,則可能會導致內存泄漏。因此,在實現跨服務共享內存時,需要確保使用內存池,並在使用之後及時釋放內存。

總而言之,要避免Skynet網路層內存泄漏,需要注意在服務初始化和結束時分配和釋放內空寬存、正確處理消息和協作操作、使用內存池並在使用之後及時釋放內存。

❽ 常見的內存泄漏原因及解決方法

(Memory Leak,內存泄漏)

當一個對象已經不需要再使用本該被回收時,另外一個正在使用的對象持有它的引用從而導致它不能被回收,這導致本該被回收的對象不能被回收而停留在堆內存中,這就產生了內存泄漏。

內存泄漏是造成應用程序OOM的主要原因之一。我們知道Android系統為每個應用程序分配的內存是有限的,而當一個應用中產生的內存泄漏比較多時,這就難免會導致應用所需要的內存超過系統分配的內存限額,這就造成了內存溢出從而導致應用Crash。

因為內存泄漏是在堆內存中,所以對我們來說並不是可見的。通常我們可以藉助MAT、LeakCanary等工具來檢測應用程序是否存在內存泄漏。
1、MAT是一款強大的內存分析工具,功能繁多而復雜。
2、LeakCanary則是由Square開源的一款輕量級的第三方內存泄漏檢測工具,當檢測到程序中產生內存泄漏時,它將以最直觀的方式告訴我們哪裡產生了內存泄漏和導致誰泄漏了而不能被回收。

由於單例的靜態特性使得其生命周期和應用的生命周期一樣長,如果一個對象已經不再需要使用了,而單例對象還持有該對象的引用,就會使得該對象不能被正常回收,從而導致了內存泄漏。
示例:防止單例導致內存泄漏的實例

這樣不管傳入什麼Context最終將使用Application的Context,而單例的生命周期和應用的一樣長,這樣就防止了內存泄漏。???

例如,有時候我們可能會在啟動頻繁的Activity中,為了避免重復創建相同的數據資源,可能會出現如下寫法:

這樣在Activity內部創建了一個非靜態內部類的單例,每次啟動Activity時都會使用該單例的數據。雖然這樣避免了資源的重復創建,但是這種寫法卻會造成內存泄漏。因為非靜態內部類默認會持有外部類的引用,而該非靜態內部類又創建了一個靜態的實例,該實例的生命周期和應用的一樣長,這就導致了該靜態實例一直會持有該Activity的引用,從而導致Activity的內存資源不能被正常回收。
解決方法 :將該內部類設為靜態內部類或將該內部類抽取出來封裝成一個單例,如果需要使用Context,就使用Application的Context。

示例:創建匿名內部類的靜態對象

1、從Android的角度
當Android應用程序啟動時,該應用程序的主線程會自動創建一個Looper對象和與之關聯的MessageQueue。當主線程中實例化一個Handler對象後,它就會自動與主線程Looper的MessageQueue關聯起來。所有發送到MessageQueue的Messag都會持有Handler的引用,所以Looper會據此回調Handle的handleMessage()方法來處理消息。只要MessageQueue中有未處理的Message,Looper就會不斷的從中取出並交給Handler處理。另外,主線程的Looper對象會伴隨該應用程序的整個生命周期。
2、 Java角度
在Java中,非靜態內部類和匿名類內部類都會潛在持有它們所屬的外部類的引用,但是靜態內部類卻不會。

對上述的示例進行分析,當MainActivity結束時,未處理的消息持有handler的引用,而handler又持有它所屬的外部類也就是MainActivity的引用。這條引用關系會一直保持直到消息得到處理,這樣阻止了MainActivity被垃圾回收器回收,從而造成了內存泄漏。
解決方法 :將Handler類獨立出來或者使用靜態內部類,這樣便可以避免內存泄漏。

示例:AsyncTask和Runnable

AsyncTask和Runnable都使用了匿名內部類,那麼它們將持有其所在Activity的隱式引用。如果任務在Activity銷毀之前還未完成,那麼將導致Activity的內存資源無法被回收,從而造成內存泄漏。
解決方法 :將AsyncTask和Runnable類獨立出來或者使用靜態內部類,這樣便可以避免內存泄漏。

對於使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源,應該在Activity銷毀時及時關閉或者注銷,否則這些資源將不會被回收,從而造成內存泄漏。

1)比如在Activity中register了一個BraodcastReceiver,但在Activity結束後沒有unregister該BraodcastReceiver。
2)資源性對象比如Cursor,Stream、File文件等往往都用了一些緩沖,我們在不使用的時候,應該及時關閉它們,以便它們的緩沖及時回收內存。它們的緩沖不僅存在於 java虛擬機內,還存在於java虛擬機外。如果我們僅僅是把它的引用設置為null,而不關閉它們,往往會造成內存泄漏。
3)對於資源性對象在不使用的時候,應該調用它的close()函數將其關閉掉,然後再設置為null。在我們的程序退出時一定要確保我們的資源性對象已經關閉。
4)Bitmap對象不在使用時調用recycle()釋放內存。2.3以後的bitmap應該是不需要手動recycle了,內存已經在java層了。

初始時ListView會從BaseAdapter中根據當前的屏幕布局實例化一定數量的View對象,同時ListView會將這些View對象緩存起來。當向上滾動ListView時,原先位於最上面的Item的View對象會被回收,然後被用來構造新出現在下面的Item。這個構造過程就是由getView()方法完成的,getView()的第二個形參convertView就是被緩存起來的Item的View對象(初始化時緩存中沒有View對象則convertView是null)。

構造Adapter時,沒有使用緩存的convertView。
解決方法 :在構造Adapter時,使用緩存的convertView。

我們通常把一些對象的引用加入到了集合容器(比如ArrayList)中,當我們不需要該對象時,並沒有把它的引用從集合中清理掉,這樣這個集合就會越來越大。如果這個集合是static的話,那情況就更嚴重了。
解決方法 :在退出程序之前,將集合里的東西clear,然後置為null,再退出程序。

當我們不要使用WebView對象時,應該調用它的destory()函數來銷毀它,並釋放其佔用的內存,否則其長期佔用的內存也不能被回收,從而造成內存泄露。
解決方法 :為WebView另外開啟一個進程,通過AIDL與主線程進行通信,WebView所在的進程可以根據業務的需要選擇合適的時機進行銷毀,從而達到內存的完整釋放。

1、在涉及使用Context時,對於生命周期比Activity長的對象應該使用Application的Context。凡是使用Context優先考慮Application的Context,當然它並不是萬能的,對於有些地方則必須使用Activity的Context。對於Application,Service,Activity三者的Context的應用場景如下:

其中,NO1表示Application和Service可以啟動一個Activity,不過需要創建一個新的task任務隊列。而對於Dialog而言,只有在Activity中才能創建。除此之外三者都可以使用。

2、對於需要在靜態內部類中使用非靜態外部成員變數(如:Context、View ),可以在靜態內部類中使用弱引用來引用外部類的變數來避免內存泄漏。
3、對於不再需要使用的對象,顯示的將其賦值為null,比如使用完Bitmap後先調用recycle(),再賦為null。
4、保持對對象生命周期的敏感,特別注意單例、靜態對象、全局性集合等的生命周期。
5、對於生命周期比Activity長的內部類對象,並且內部類中使用了外部類的成員變數,可以這樣做避免內存泄漏:
1)將內部類改為靜態內部類
2)靜態內部類中使用弱引用來引用外部類的成員變數

Android內存泄漏總結

❾ 什麼是內存泄露內存泄露該如何解決

1、內存泄漏指由於疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。

2、一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的,

使用完後必須顯式釋放的內存。應用程序一般使用malloc,calloc,realloc,new等函數從堆

中分配到一塊內存,使用完後,程序必須負責相應的調用free或delete釋放該內存塊,否則

這塊內存就不能被再次使用,就是這塊內存泄漏了。

3、內存泄露多數屬於程序本身設計問題,有以下幾種解決方法:

1)從程序內部重新編譯。養成良好的編碼習慣,盡量在涉及內存的程序段,檢測出內存泄露。

2)結束程序,內存自然就會被操作系統回收。

3)重新啟動電腦後,立刻恢復。

❿ threadlocal內存泄漏原因和解決方案

首先是因為 ThreadLocal 是基於 ThreadLocalMap 實現的,其中 ThreadLocalMap 的 Entry 繼承了 WeakReference ,而 Entry 對象中的 key 使用了 WeakReference 封裝,也就是說, Entry 中的 key 是一個弱引用類型,對於弱引用來說,它只能存活到下次 GC 之前 ;如果此時一個線程調用了 ThreadLocalMap 的 set 設置變數,當前的 ThreadLocalMap 就會新增一條記錄,但由於發生了一次垃圾回收,這樣就會造游陵喊成一個結果: key 值被回收掉了,但神野是 value 值還在內存中,而且如果線程一直存在的話,那麼它的 value 值就會一直存在

可知是汪凳因為value 值沒有被回收掉導致內存泄露,使用完 key 值之後,將 value 值通過 remove 方法 remove 掉,也就防止了內存泄漏

參考文章 https://m.html.cn/softprog/java/66005.html

閱讀全文

與內存泄漏的原因及解決方法相關的資料

熱點內容
排煙風口與短管連接方法 瀏覽:701
姚桐斌研究的方法 瀏覽:737
引伸計安裝方法 瀏覽:616
吉娃娃手機使用方法 瀏覽:845
安卓系統通訊錄設置在哪裡設置方法 瀏覽:815
怎麼備孕最好方法 瀏覽:812
頸椎病治療方法用什麼中葯治 瀏覽:246
水鑽打空調眼兒使用方法視頻 瀏覽:819
口腔頜面腫瘤治療方法 瀏覽:959
沖成人奶粉的正確方法 瀏覽:193
404x125的簡便運算方法 瀏覽:10
水泥多孔磚砌牆方法圖片 瀏覽:705
孢穀草種植方法 瀏覽:283
萵筍青菜種植方法 瀏覽:736
前列腺增生怎麼治療方法 瀏覽:846
12伏蓄電池存電量計算方法 瀏覽:219
沖壓工36技計算方法計算實例 瀏覽:858
骨化三醇免疫治療方法 瀏覽:306
三聯療法如何服用方法 瀏覽:426
93乘43加91的簡便方法 瀏覽:393