如何在链接列表中连续插入时处理内存泄漏?

时间:2012-04-10 06:35:28

标签: java android memory-leaks garbage-collection

我有以下函数,它是从连续运行的Thread的run()连续调用的。

private LinkedList<short[]> playerData = new LinkedList<short[]>();

public synchronized void setPlayerData(short[] buffer) {
        // Log.i(LOG_TAG, "Inside setData..");
        playerData.addLast(buffer);
        if (playerData.size() > 10) {
            // Log.i(LOG_TAG, "playerData not empty");
            playerData.removeFirst();
        }
    }

现在DDMS的分配跟踪器表示在addLast()中创建了很多对象(实际上是在addLastImpl()内部),所以我想明确地删除这些数组,以便它们是在Heap中总是有足够的内存。现在,

  1. System.gc()选项无效,因为每次调用setPlayerData()时都会同时调用它。
  2. GC_CONCURRENT占用了所有CPU周期,因为app对时间非常敏感,甚至几秒钟的延迟也是不可接受的。
  3. 有关LogCat的信息,请参阅link,这是我解决整个synarion的另一个问题。在这个帖子中,我只是试图通过将它分成一组小问题来解决这个更大的问题。

    可能的解决方案可能的解决方案是通过删除不需要的数组来释放内存空间。但是在Java中我们如何释放由new运算符创建的数组?即

    short[] buffer = new short[320];
    // do some operation on buffer
    /// now how can I explicitly free memory by deleting the buffer, when its job is over..
    

    我知道有垃圾收集来处理所有这些事情。但是在我的应用中, GC_CONCURRENT 会一直吃掉。由于这个原因,其他过程也很匮乏。如果我能够显式释放内存,即在C ++中删除,那将是很棒的。您可以在此处查看LogCat信息... A detailed question regarding my problem

    编辑2 3.将数组分配为null

    这有什么用? null数组将被安排到垃圾收集,我想避免,因为从一个线程连续调用该方法(每20毫秒)。如果我将数组赋值为null,GC_FOR_MALLOC消息将填充LogCat ...

5 个答案:

答案 0 :(得分:7)

显式删除对象无法解决您的问题...基本上是因为在Java中无法做到这一点。

如果您真的为CMS收集器创建了太多垃圾来处理,那么唯一的解决方案是使用对象池来回收buffer个对象,而不是将它们放在上面GC要处理的问题。但是,您需要注意不要将当前问题替换为其他问题:

  • 可能需要“清理”(归零)回收的物体。
  • 设计不良的对象池可能是内存泄漏。
  • 设计不良的对象池可能是并发瓶颈。
  • 设计不良的对象池可能会增加GC开销,尤其是在运行堆太小的情况下。

另一方面,您真正的问题可能是您的堆太小而无法运行您正在运行的应用程序。如果运行得太接近极限,GC每次都不会回收太多垃圾。由于运行GC的成本与非垃圾量成正比,因此很容易看出,当堆接近满时,GC的效率是非线性的。

答案 1 :(得分:4)

使用后,只需将对象设置为 NULL 垃圾收集器将自动处理它。实际上垃圾收集器会在代码无法访问您的对象时启动,因此它会破坏它们以释放空间。

答案 2 :(得分:2)

Java没有删除操作符。当代码部分不再使用它时,垃圾收集器会自动销毁对象。

这就是当一个对象无法访问时,垃圾收集器会破坏该对象并释放相关的内存。

我读了编辑,也许你可以用byte []缓冲池来解决你的问题。所以垃圾收集器不需要一直垃圾填充缓冲区。

private LinkedList playerData = new LinkedList();

public synchronized void setPlayerData(short[] buffer) {
  // Log.i(LOG_TAG, "Inside setData..");
  playerData.addLast(buffer);
  if (playerData.size() > 10) {
    // Log.i(LOG_TAG, "playerData not empty");
    byte[] buffer = playerData.removeFirst();
    // here return the buffer to the pool to reuse it
  }

}

答案 3 :(得分:1)

如果您遇到垃圾收集器问题,最好的方法是分配更少的新内存。一种方法是使用object pools。基本上,重用一个不再需要的缓冲区而不是创建一个新缓冲区。

答案 4 :(得分:1)

Java中没有“等效”运算符。系统在后台执行垃圾收集。没有明确的方法调用将保证内存将立即释放。