2012-09-12 130 views
3

編輯:我認爲在解析xml的代碼中有一個邏輯錯誤,所以如果它正確寫入不應該有任何泄漏。奇怪的內存泄漏

所以我添加了我的項目一個AsyncTask類,我前段時間爲快速測試目的而寫,但它導致內存泄漏錯誤。

我相信它是負責任的,因爲當我刪除它泄漏問題消失。

這裏是堆轉儲文件(已轉換)http://www7.zippyshare.com/v/83628026/file.html

package com.example.xmldl; 

import java.io.IOException; 
import java.io.InputStream; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import org.xmlpull.v1.XmlPullParser; 
import org.xmlpull.v1.XmlPullParserException; 
import android.os.AsyncTask; 
import android.util.Xml; 

public class Dlxml extends AsyncTask<String, Void, Void> { 
    //adding or removing Override didnt matter just to let you know 
    InputStream istream = null; 
    protected Void doInBackground(String... url){ 

     try { 
      downloadXml(url[0]); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    private void downloadXml(String url) throws IOException { 
     try { 
      URL mUrl = new URL(url); 
      HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection(); 
      istream = urlConnection.getInputStream();   
      XmlPullParser parser = Xml.newPullParser(); 
      parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); 
      parser.setInput(istream, null); 
      parser.nextTag(); 
      parser.require(XmlPullParser.START_TAG, null, "resources"); 
      while (parser.next() != XmlPullParser.END_TAG) { 
       if (parser.getEventType() == XmlPullParser.TEXT) {     
        parser.nextTag();     
       } 
       if (parser.getEventType() != XmlPullParser.START_TAG) { 
        continue; 
       }    
      }   
     } catch (MalformedURLException e) { 
      e.printStackTrace();   
     } catch (XmlPullParserException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     finally { 
      istream.close();    
     } 

    } 

} 
+0

什麼是實際的錯誤信息? –

+0

這是內存泄漏... – 2012-09-12 13:23:07

+0

如果您將轉儲視圖的屏幕截圖設置爲不強制我們在當前PC上設置MemAnalyzer,那將會非常簡單。謝謝 – AlexN

回答

0

我不相信你關閉你的InputStream:

private void downloadXml(String url) throws IOException { 
    try { 
     URL mUrl = new URL(url); 
     HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection(); 
     InputStream istream = urlConnection.getInputStream();   
     XmlPullParser parser = Xml.newPullParser(); 
     parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); 
     parser.setInput(istream, null); 
     parser.nextTag(); 
     parser.require(XmlPullParser.START_TAG, null, "resources"); 
     while (parser.next() != XmlPullParser.END_TAG) { 
      if (parser.getEventType() == XmlPullParser.TEXT) {     
       parser.nextTag();     
      } 
      if (parser.getEventType() != XmlPullParser.START_TAG) { 
       continue; 
      }    
     } 
     // dont forget to close the input stream! 
     istream.close(); 
    } catch (IOException e) { 
     //error closing istream 
     e.printStackTrace();   
    } catch (MalformedURLException e) { 
     e.printStackTrace();   
    } catch (XmlPullParserException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    finally { 

    } 

} 
+0

對不起,我最後關閉了inputstream。以某種方式粘貼時刪除。 – FireFly

+0

哦。哈哈。傻我 – petey

+0

不,這是我的錯對不起。 – FireFly

0

在這段代碼中我看不到可能存在內存泄漏問題。所以它必須在這個包含的代碼中。因爲我不知道XmlPullParser可能在那裏。但無論如何,輸入流應該在最後分支被關閉,你必須修改代碼

finally { 
      istream.close();    
     } 

不好:)

finally { 
     if(istream != null){ 
      istream.close();    
     } 
} 

更好:)

+0

這就是爲什麼這是泄漏是奇怪的有這麼少的代碼,導致內存泄漏,我認爲。但它是一個完整的內存泄漏:/ Btw:我相信這是導致內存泄漏的類,因爲如果嘗試從另一個Activity執行此操作,泄漏會像地獄一樣彈出。 – FireFly

+0

感謝您的建議:) – FireFly

0

在大多數情況下內存泄漏在Android中發生在我身上,它來自線程問題。所以,我可以首先問你如何調用這個類(從AsyncTask擴展的Dlxml)。確保你沒有使用匿名變量,比如「new Dlxml()。execute()」,因爲Android的垃圾收集器可能需要很長時間才能檢測到線程不再有用(如果你正在使用一個加載器名單,它可以產生大量的泄漏)。我想推薦你在執行並行處理之前檢查這兩點:

  • 總是使用靜態變量來實例化加載器。這有助於防止泄漏,甚至是Android警告註釋。嘗試在線程和處理程序問題上使用靜態類變量;
  • 請注意您正在調用哪個線程來更改視圖的方法。如果你在一個不是main的線程中調用一個方法,並且改變了視圖,logcat會拋出一個關於泄漏的消息。對此,利用活動的runonuithread方法;

重要的東西:我想通了,你已經使用的AsyncTask,只有在後臺做了很多事情。這些東西是否改變了這個觀點?您可以在doInBackground上進行下載,並在onPostExecute更改視圖。

你也可以有興趣在這些鏈接:

+0

我正在使用匿名變量,所以我會馬上改變,看看是否修復。我沒有發佈任何東西,但這項任務是發佈一些日誌消息到logcat,但爲了便於閱讀,我刪除了它。你能給出你的第一個建議的代碼示例嗎? – FireFly

+0

更改我的代碼,如你所建議的,但它並沒有阻止它:Dlxml getXml = new Dlxml(); \t getXml.execute(mUrl); // mUrl是一個靜態變量 – FireFly

+0

正如matheszabi所發佈的,在代碼片段中看到內存泄漏很難(如果確實存在)。還有一件事要問:你在用什麼來關閉你的連接?我通常會看到這三個關閉Web服務請求: - httpPost.abort(); - closeInputStream(); - httpClient.getConnectionManager()。shutdown(); 希望它以某種方式幫助... :) – mthama