Android中的内存泄漏

时间:2012-01-23 10:46:50

标签: android

我遇到了与内存泄漏有关的问题。在我的应用程序中,我必须从视频文件中读取2MB数据,并且当Activity的onCreate方法调用时,相关的方法始终调用,然后在代码中分配2MB字节数组的相同语句,在经过事务后返回OutofMemory异常因为堆内存超过10到15次尝试。代码解释如下(这是我整个代码的一部分):

//Reading DRM video from sdcard
                File file = new File("/sdcard/TvAnyTime/watch/"+IDValue+".mp4");
                   try {
                          is = new FileInputStream(file);
                   } catch (FileNotFoundException e2) {
                          e2.printStackTrace();
                   }
                   //reading 2^21 bytes
                   fileData = new byte[2097152];
                   int read = 0;
                   while(read != fileData.length) {
                      try {
                    read += is.read(fileData, read, fileData.length - read);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                   }

                   //The finalHashPattern is then xored across the video file 2^10 times
                   for(int i=0;i<2097152;i+=2048)
                   {
                    byte[] res = new byte[2048];
                    bytesafterXor = new byte[2048];

                    for(int j=0;j<2048;j++)
                    {

                        res[j] = fileData[i+j];
                        bytesafterXor[j] = (byte)(res[j]^finalhash[j]);
                        finaldatafile[i+j] = bytesafterXor[j];
                    }

                    finalHashafterXor.add(bytesafterXor);

                   }

语句fileData = new byte[2097152];负责OutOfMemory异常,因为每次调用onCreate时都会分配它。我们可以通过每次分配大内存来阻止它吗?我们可以用大块的数据来读它吗?请建议我正确的解决方案。

提前致谢。

4 个答案:

答案 0 :(得分:2)

您是否考虑过处理读取字节的循环内的输入,而不是读取所有字节

fileData = new byte[2048];
int read = 0;
while(read != fileData.length) {
    try {
        read += is.read(fileData, read, fileData.length);
        for(int i = 0; i < 2048; i++) {
            // Processing here
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

答案 1 :(得分:1)

你可以将 fileData 作为静态指针,然后 onCreate 只分配内存一次,当 fileData == NULL ;

答案 2 :(得分:0)

您可以将此关键文件处理从Java代码排除到本机代码。 http://marakana.com/forums/android/examples/49.html

http://android.wooyd.org/JNIExample/files/JNIExample.pdf

答案 3 :(得分:0)

好的,因为我在等待同行评审时对“神秘”的Kingamajick的答案的编辑消失了,所以这里是如何将文件(或一般的流)整理成一个块:

fileData = new byte[2048];
try {

  int c = 0;
  while( (c = is.read(fileData)) >= 0 ) {

    // Process all bytes from fileData[0] through fileData[c-1], e.g.:   
    for(int i = 0; i < c; i++) {
      // do something with fileData[i]
      // ...
    }
  }

} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

请注意,对于文件,缓冲区(上面的fileData)很可能总是被读取操作完全填充,直到文件中没有足够的字节来读取。例如,当从网络流中读取时,通常不是这种情况,因为数据并不总是立即可用,并且当它变得可用时,它可能与最后一个网络数据包中到达的数据一样多。但是,上述方法适用于所有流。

编辑:

从你的评论中我认为你不想处理整个文件而只需要处理前2mb。在这种情况下,您可以稍微修改上述方法,例如:

fileData = new byte[2048];

int leftToRead = 2048*1024; // Total amount of bytes you want to read.

try {

  int c = 0;

  // How many bytes may we read at once?
  int maxRead = Math.min( fileData.length, leftToRead );

  while( (leftToRead > 0) && (c = is.read(fileData, 0, maxRead)) >= 0 ) {

    // Process all bytes from fileData[0] through fileData[c-1], e.g.:   
    for(int i = 0; i < c; i++) {
      // do something with fileData[i]
      // ...
    }

    // We read c bytes, so we may have some bytes left:
    leftToRead -= c;

    // How many bytes may we read at once?
    maxRead = Math.min( fileData.length, leftToRead );

  }

  // Optionally:
  if ( leftToRead > 0 ) {
    System.out.println("Premature end of file.");
  }

} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

当您在代码摘录中逐字节处理文件时,您基本上可以自由选择fileData缓冲区的大小。较小的缓冲区不会提供任何实际好处,因为它可能会对底层文件系统造成更多的读取操作。从1kb到64kb的范围通常是一个很好的尺寸。