2012-09-12 88 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