導航:首頁 > 操作系統 > android避免內存泄露

android避免內存泄露

發布時間:2022-10-01 15:19:20

android scrollview內存溢出怎麼解決

android scrollview內存溢出通常是由內存泄露導致。
1、內存泄露導致
由於我們程序的失誤,長期保持某些資源(如Context)的引用,垃圾回收器就無法回收它,當然該對象佔用的內存就無法被使用,這就造成內存泄露。
Android 中常見就是Activity被引用在調用finish之後卻沒有釋放,第二次打開activity又重新創建,這樣的內存泄露不斷的發生,則會導致內存的溢出。
Android的每個應用程序都會使用一個專有的Dalvik虛擬機實例來運行,它是由Zygote服務進程孵化出來的,也就是說每個應用程序都是在屬於自己的進程中運行的。Android為不同類型的進程分配了不同的內存使用上限,如果程序在運行過程中出現了內存泄漏的而造成應用進程使用的內存超過了這個上限,則會被系統視為內存泄漏,從而被kill掉,這使得僅僅自己的進程被kill掉,而不會影響其他進程.
2、佔用內存較多的對象
保存了多個耗用內存過大的對象(如Bitmap)或載入單個超大的圖片,造成內存超出限制。
使用方法比較簡單:
· 選擇DDMS視圖,並打開Devices視圖和Heap視圖
· 點擊選擇要監控的進程,比如:上圖中我選擇的是system_process
· 選中Devices視圖界面上的"update heap" 圖標
· 點擊Heap視圖中的"Cause GC" 按鈕(相當於向虛擬機發送了一次GC請求的操作)
在Heap視圖中選擇想要監控的Type,一般我們會觀察dataobject的 total size的變化,正常情況下total size的值會穩定在一個有限的范圍內,也就說程序中的代碼良好,沒有造成程序中的對象不被回收的情況。如果代碼中存在沒有釋放對象引用的情況,那麼data object的total size在每次GC之後都不會有明顯的回落,隨著操作次數的增加而total size也在不斷的增加。(說明:選擇好data object後,不斷的操作應用,這樣才可以看出total size的變化)。如果totalsize確實是在不斷增加而沒有回落,說明程序中有沒有被釋放的資源引用。那麼我們應該怎麼來定位呢?
Android中內存泄露定位
通過DDMS工具可以判斷應用程序中是否存在內存泄漏的問題,那又如何定位到具體出現問題的代碼片段,最終找到問題所在呢?內存分析工具MAT Memory Analyzer Tool解決了這一難題。MAT工具是一個Eclipse 插件,同時也有單獨的RCP 客戶端,MAT工具的解析文件是.hprof,這個文件存放了某進程的內存快照。MAT工具定位內存泄漏具體位置的方法如下:
① 生成.hprof文件。Eclipse中生成.hprof文件的方法有很多,不同Android版本中生成.hprof的方式也稍有差別,但它們整體思路是一樣的。我們在DDMS界面選中想要分析的應用進程,在Devices視圖界面上方的一行圖標按鈕中,同時選中「Update Heap」和「Dump HPROF file」兩個按鈕,這時DDMS將會自動生成當前選中進程的.hprof文件。
② 將.hprof 文件導入到MAT工具中,MAT工具會自動解析並生成報告,點擊「Dominator Tree」按鈕,並按包分組,選擇已定義的包類點右鍵,在彈出的菜單中選擇List objects﹥With incoming references,這時會列出所有可疑的類。右鍵點擊某一項,並選擇Path to GC Roots﹥excludeweak/soft references,MAT工具會進一步篩選出跟程序相關的所有內存泄漏的類。這樣就可以追蹤到某一個產生內存泄漏的類的具體代碼中。
使用MAT內存分析工具查找內存泄漏的根本思路是找到哪個類的對象的引用沒有被釋放,然後分析沒有被釋放的原因,最終定位到代碼中哪些片段存在著內存泄漏。

② android webview怎樣開辟新的進程避免內存泄露

Android中的WebView組件,內存泄漏的問題一直沒有非常有效的解決方案。只能去自己集成騰訊的X5內核。

③ android webview怎樣開辟新的進程避免內存泄露

使用crosswalk
具體使用
1)在布局文件中
<org.xwalk.core.XWalkView android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</org.xwalk.core.XWalkView>
2)在activity
import android.app.Activity;
import android.os.Bundle;

import org.xwalk.core.XWalkView;

public class MyActivity extends Activity {
private XWalkView mXWalkView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mXWalkView = (XWalkView) findViewById(R.id.activity_main);
mXWalkView.load("", null);
}

@Override
protected void onPause() {
super.onPause();
if (mXWalkView != null) {
mXWalkView.pauseTimers();
mXWalkView.onHide();
}
}

@Override
protected void onResume() {
super.onResume();
if (mXWalkView != null) {
mXWalkView.resumeTimers();
mXWalkView.onShow();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mXWalkView != null) {
mXWalkView.onDestroy();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mXWalkView != null) {
mXWalkView.onActivityResult(requestCode, resultCode, data);
}
}

@Override
protected void onNewIntent(Intent intent) {
if (mXWalkView != null) {
mXWalkView.onNewIntent(intent);
}
}
}

缺點:.so文件太大,導致打包後的apk文件很大(一般20多M)

④ android中怎麼防止oom

內存泄露的原因:
1. Handler造成內存泄漏

private Handler handler = new Handler(){
@Override
public void handMessage(Message msg){

}
}
當使用內部類(包括匿名類)來創建Handler時,Handler對象會隱式地持有一個外部類對象(通常是一個Activity)的引用。
而Handler通常會伴隨一個耗時的後台線程(例如訪問網路或者從網路上拉取圖片)一起出現,這個後台線程在任務執行完畢(例如圖片下載完成)之後,通過消息機制通知Handler,然後Handler把圖片更新到界面上(主線程中)。
當用戶在網路請求過程中關閉了Activity,正常情況下,Activity不再被使用,它就有可能在GC檢查時被回收掉。但是由於這時線程尚未執行完,而該線程持有Handler的引用,Handler持有Activity的引用,就導致Activity無法被回收(即內存泄露),直到網路請求結束(例如圖片下載完成)。
另外,如果你執行了Handler的postDelayed()方法,該方法會將你的Handler裝入一個Message,並把這條Message推到MessageQueue中,那麼在你設定的delay到達之前,會有一條MessageQueue —> Message —> Handler —> Activity的鏈,導致你的Activity被持有引用而無法被回收。
使用Handler導致內存泄露的解決辦法:
一、通過程序邏輯進行保護
A. 在finish Activity的時候停掉你的後台線程,線程停掉了,就相當於切斷了Handler與外部連接的線,Activity自然會在合適的時候被回收。
B. 如果Handler被delay的Message持有了引用,那麼使用相應的Handler的removeCallbacks()方法,把消息對象從消息隊列中移除即可。
二、將Handler聲明為靜態類
靜態類不持有外部類的引用對象,所以Activity可以隨意被回收。
static class MyHandler extends Handler{

@Override
public void handleMessage(Message msg){
}
}
此時由於Handler不再持有外部類對象的引用,導致程序不允許你在Handler中操作Activity中的對象。所以你需要在Handler中增加一個對Activity的弱引用(WeakReference)
static class MyHandler extends Handler{
WeakReference<Activity> activityReference;
public MyHandler(Activity activity){
activityReference = new WeakReference<Activity>(activity);
}

@Override
public void handleMessage(Message msg){
final Activity activity = activityReference.get();
}
}
對應以上的代碼,用戶在關閉Activity之後,就算後台線程還沒結束,但由於僅有一條來自Handler的弱引用指向Activity,所以GC仍然會在檢查的時候把Activity回收掉。
So, 關於Handler內存泄露的問題就不會出現。

⑤ android怎麼防止內存溢出

Android的內存主要表現在:
1. 在Android平台上,長期保持一些資源的引用,造成一些內存不能釋放,帶來的內存泄露問題很多。比如:Context(下文中提到的Activity都是Context),在一些你需要保持你的首個類對象狀態,並且把狀態傳入其他類對象中時,這樣消除掉首個類對象之前,你必須先把接收類對象釋放掉。需要注意一點的是:因為在Java或者Android內存機制中,頂點的結點釋放前必須保證其他對象沒有調用才能被系統GC回收釋放。我們來看一段代碼:
@Override
protected void onCreate(Bundlestate) {
super.onCreate(state);
TextViewlabel = new TextView(this);
label.setText("Leaksare bad");
setContentView(label);
}
這個代碼的意思就是我們把一個TextView的實例載入到了我們正在運行的Activity(Context)當中,因此,通過GC回收機制,我們知道,要釋放Context,就必須先釋放掉引用他的一些對象。如果沒有,那在要釋放Context的時候,你會發現會有大量的內存溢出。所以在你不小心的情況下內存溢出是一件非常容易的事情。保存一些對象時,同時也會造成內存泄露。最簡單的比如說點陣圖(Bitmap),比如說:在屏幕旋轉時,會破壞當前保持的一個Activity狀態,並且重新申請生成新的Activity,直到新的Activity狀態被保存。我們再看一段代碼:
privatestatic DrawablesBackground;
@Override
protected void onCreate(Bundlestate) {
super.onCreate(state);
TextView label = newTextView(this);
label.setText("Leaks arebad");
if (sBackground == null){
sBackground =getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
這個代碼是非常快的同時也是錯誤的。它的內存泄露很容易出在屏幕轉移的方向上。雖然我們會發現沒有顯示的保存Context這個實例,但是當我們把繪制的圖連接到一個視圖的時候,Drawable就會將被View設置為回調,這就說明,在上述的代碼中,其實在繪制TextView到活動中的時候,我們已經引用到了這個Activity。鏈接情況可以表現為:Drawable->TextView->Context。
所以在想要釋放Context的時候,其實還是保存在內存中,並沒有得到釋放。
如何避免這種情況:主要在於。線程最容易出錯。大家不要小看線程,在Android裡面線程最容易造成內存泄露。線程產生內存泄露的主要原因在於線程生命周期的不可控。下面有一段代碼:
publicclass MyTest extendsActivity {
@Override
publicvoid onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
privateclass MyThread extends Thread{
@Override
public void run() {
super.run();
//do somthing
}
}
}
代碼很簡單,但是在Android上又來新問題了,當我們在切換視圖屏幕的時候(橫豎屏),就會重新建立橫屏或者豎屏的Activity。我們形象的認為之前建立的Activity會被回收,但是事實如何呢?Java機制不會給你同樣的感受,在我們釋放Activity之前,因為run函數沒有結束,這樣MyThread並沒有銷毀,因此引用它的Activity(Mytest)也有沒有被銷毀,因此也帶來的內存泄露問題。
有些人喜歡用Android提供的AsyncTask,但事實上AsyncTask的問題更加嚴重,Thread只有在run函數不結束時才出現這種內存泄露問題,然而AsyncTask內部的實現機制是運用了ThreadPoolExcutor,該類產生的Thread對象的生命周期是不確定的,是應用程序無法控制的,因此如果AsyncTask作為Activity的內部類,就更容易出現內存泄露的問題。
線程問題的改進方式主要有:
l 將線程的內部類,改為靜態內部類。
l 在程序中盡量採用弱引用保存Context。
2. 萬惡的bitmap。。。
Bitmap是一個很萬惡的對象,對於一個內存對象,如果該對象所佔內存過大,在超出了系統的內存限制時候,內存泄露問題就很明顯了。。
解決bitmap主要是要解決在內存盡量不保存它或者使得采樣率變小。在很多場合下,因為我們的圖片像素很高,而對於手機屏幕尺寸來說我們並不用那麼高像素比例的圖片來載入時,我們就可以先把圖片的采樣率降低在做原來的UI操作。
如果在我們不需要保存bitmap對象的引用時候,我們還可以用軟引用來做替換。具體的實例代碼google上面也有很多。
綜上所述,要避免內存泄露,主要要遵循以下幾點:
第一:不要為Context長期保存引用(要引用Context就要使得引用對象和它本身的生命周期保持一致)。
第二:如果要使用到Context,盡量使用ApplicationContext去代替Context,因為ApplicationContext的生命周期較長,引用情況下不會造成內存泄露問題
第三:在你不控制對象的生命周期的情況下避免在你的Activity中使用static變數。盡量使用WeakReference去代替一個static。
第四:垃圾回收器並不保證能准確回收內存,這樣在使用自己需要的內容時,主要生命周期和及時釋放掉不需要的對象。盡量在Activity的生命周期結束時,在onDestroy中把我們做引用的其他對象做釋放,比如:cursor.close()。
其實我們可以在很多方面使用更少的代碼去完成程序。比如:我們可以多的使用9patch圖片等。有很多細節地方都可以值得我們去發現、挖掘更多的內存問題。我們要是能做到C/C++對於程序的「誰創建,誰釋放」原則,那我們對於內存的把握,並不比Java或Android本身的GC機制差,而且更好的控制內存,能使我們的手機運行得更流暢。

轉載

⑥ android 怎麼樣解決webview內存泄露

android webview 載入html都會導致內存溢出
1、使用crosswalk
具體使用
1)在布局文件中

<org.xwalk.core.XWalkView android:id="@+id/activity_main"
xmlns:android=""
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</org.xwalk.core.XWalkView>

2)在activity

import android.app.Activity;
import android.os.Bundle;

import org.xwalk.core.XWalkView;

public class MyActivity extends Activity {
private XWalkView mXWalkView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mXWalkView = (XWalkView) findViewById(R.id.activity_main);
mXWalkView.load("", null);
}

@Override
protected void onPause() {
super.onPause();
if (mXWalkView != null) {
mXWalkView.pauseTimers();
mXWalkView.onHide();
}
}

@Override
protected void onResume() {
super.onResume();
if (mXWalkView != null) {
mXWalkView.resumeTimers();
mXWalkView.onShow();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mXWalkView != null) {
mXWalkView.onDestroy();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mXWalkView != null) {
mXWalkView.onActivityResult(requestCode, resultCode, data);
}
}

@Override
protected void onNewIntent(Intent intent) {
if (mXWalkView != null) {
mXWalkView.onNewIntent(intent);
}
}
}

缺點:.so文件太大,導致打包後的apk文件很大(一般20多M)

⑦ android中用getApplicationContext會不會避免某些內存泄漏問題

Android上 ,Context可以用於很多操作,但是大部分時候是用來載入以及使用資源。這就是為什麼所有的widgets在他們的構造函數中接受一個Context參數。在一般的android應用中,通常有兩種Context:分別是Activity和Application。通常的,當咱們的類和方法需要使用到context時,咱們傳遞的是Activity這個context:

@Override
protected void onCreate(Bundle state)
{
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
setContentView(label);
}

這意味著views擁有一個對整個activity的引用,也就是引用了activity所擁有的一切;通常的,這指的是完整的視圖層級結構以及所有它的資源。因此,如果泄露了一個Context(「泄漏」意味著保持著它的一個引用,從而使它不能被垃圾回收機制回收),就意味著泄漏了很多的內存。如果不小心, 泄漏一個activity的所有資源真的非常容易。
當屏幕的方向發生改變的時候,系統默認將會銷毀當前的activity並且創建一個新的activity同時保持著原有的狀態。在做這個的時候,Android會從資源重新載入應用的UI。現在,想像一下自己寫了一個應用,這個應用有一張很大的bitmap。不想再每一次旋轉的時候重新載入它。最簡單的方法讓bitmap持續作用而不隨每一個方向而重新載入 ,就是把它放進一個靜態域:

private static Drawable sBackground;
@Override
protected void onCreate(Bundle state)
{
super.onCreate(state);

TextView label = new TextView(this);

label.setText("Leaks are bad");

if (sBackground == null)
{
sBackground = getDrawable(R.drawable.large_bitmap);
}

label.setBackgroundDrawable(sBackground);

setContentView(label);
}

這段代碼很快,但是錯誤也很嚴重:它泄漏了第一個activity,這個在第一次屏幕改變時被創建的activity。當一個Drawable被關聯到一個view上,這個view就相當於在drawable上設置的一個回調。在上面的代碼片段中,這表示drawable有一個TextView的引用,而這個TextView又擁有一個activity的引用(Context),activity依次引用了幾乎所有的東西(取決於自己的代碼)。
這個例子展示了一個最簡單的Context 泄漏的情況,可以在Home screen 的源碼中看到咱們是如何解決這個問題的( 查找unbindDrawables() 方法) ,這就是當activity 被銷毀的時候將drawables 的回調設為null 。有趣的是,可能創造出一系列context泄漏的情況有很多,這非常糟糕。他們會是很快內存溢出。
有兩種簡單的方法來避免context 相關的內存泄漏。最顯著地一個是避免context 逃出他自己的范圍之外。上面的例子就展示了使用靜態引用的情況,而內部類和他們對外部類的的隱式引用也是同樣危險的。第二種方法是使用Application context 。這個context 的生存周期和應用的生存周期一樣長,而不是取決於activity 的生存周期。如果想保持一個長期生存的對象,並且這個對象需要一個context ,記得使用application 對象。可以通過調用Context.getApplicationContext() or Activity.getApplication() 來獲得。
總而言之,想要避免context 相關的內存泄漏 ,記住以下幾點:
A:不要對activity 的context 長期引用( 一個activity 的引用的生存周期應該和activity 的生命周期相同)
B:試著使用關於application的 context 來替代和activity相關的context
C:如果一個acitivity 的非靜態內部類的生命周期不受控制,那麼避免使用它;使用一個靜態的內部類並且對其中的activity 使用一個弱引用。解決這個問題的方法是使用一個靜態的內部類,並且對它的外部類有一WeakReference,就像在ViewRoot中內部類W所做的就是這么個例子。
D:垃圾回收器不能處理內存泄漏的保障。

⑧ Android中什麼情況下會導致內存泄露

集合類泄漏
集合類如果僅僅有添加元素的方法,而沒有相應的刪除機制,導致內存被佔用。如果這個集合類是全局性的變數 (比如類中的靜態屬性,全局性的 map 等即有靜態引用或 final 一直指向它),那麼沒有相應的刪除機制,很可能導致集合所佔用的內存只增不減。比如上面的典型例子就是其中一種情況,當然實際上我們在項目中肯定不會寫這么 2B 的代碼,但稍不注意還是很容易出現這種情況,比如我們都喜歡通過 HashMap 做一些緩存之類的事,這種情況就要多留一些心眼。
單例造成的內存泄漏
由於單例的靜態特性使得其生命周期跟應用的生命周期一樣長,所以如果使用不恰當的話,很容易造成內存泄漏
匿名內部類/非靜態內部類和非同步線程
非靜態內部類創建靜態實例造成的內存泄漏
有的時候我們可能會在啟動頻繁的Activity中,為了避免重復創建相同的數據資源
Handler 造成的內存泄漏
Handler 的使用造成的內存泄漏問題應該說是最為常見了,很多時候我們為了避免 ANR 而不在主線程進行耗時操作,在處理網路任務或者封裝一些請求回調等api都藉助Handler來處理,但 Handler 不是萬能的,對於 Handler 的使用代碼編寫一不規范即有可能造成內存泄漏。另外,我們知道 Handler、Message 和 MessageQueue 都是相互關聯在一起的,萬一 Handler 發送的 Message 尚未被處理,則該 Message 及發送它的 Handler 對象將被線程 MessageQueue 一直持有。
由於 Handler 屬於 TLS(Thread Local Storage) 變數, 生命周期和 Activity 是不一致的。因此這種實現方式一般很難保證跟 View 或者 Activity 的生命周期保持一致,故很容易導致無法正確釋放。

⑨ android開發內存優化之如何有效避免oom

  1. 減小對象的內存佔用

  2. 內存對象的重復利用

  3. 避免對象的內存泄露

  4. 內存使用策略優化

閱讀全文

與android避免內存泄露相關的資料

熱點內容
自動解壓失敗叫我聯系客服 瀏覽:482
易語言新手源碼 瀏覽:456
oa伺服器必須有固定ip地址 瀏覽:42
傳奇源碼分析是什麼 瀏覽:267
解放壓縮機支架 瀏覽:255
程序員禿頂搞笑相遇 瀏覽:6
IBM手機app商店叫什麼名字 瀏覽:834
jpeg壓縮質量 瀏覽:774
雲伺服器評測對比 瀏覽:145
java日期轉string 瀏覽:221
openfire源碼編譯 瀏覽:897
在線小工具箱引流網站源碼 瀏覽:337
非科班程序員自學 瀏覽:800
壓縮泡沫鞋底底材 瀏覽:219
程序員職場第一課2正確的溝通 瀏覽:679
遇到不合法app應該怎麼辦 瀏覽:91
匯編程序編譯後的文件 瀏覽:80
大智慧均線源碼 瀏覽:373
單片機排阻的作用 瀏覽:216
滴滴金融app被下架如何還款 瀏覽:212