-1

我有以下函数,它从连续运行的线程的 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() 内部),因此我想明确删除这些数组,以便它们在堆中始终有足够的内存。现在,

  1. System.gc() 选项无济于事,因为每次调用 setPlayerData() 时都会同时调用它。
  2. GC_CONCURRENT 占用了所有的 CPU 周期,因为应用程序对时间非常敏感,即使是几毫秒的延迟也是不可接受的。

有关 LogCat 信息,请参阅链接,这是我解决整个 synarion 的另一个问题。在这个线程中,我只是试图通过将它分成一组小问题来解决这个更大的问题。

一个可能的解决方案一个可能的解决方案是通过删除不需要的数组来显式释放内存空间。但是在 Java 中,我们如何释放由操作符创建的数组new呢?IE

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 信息...关于我的问题的详细问题

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

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

4

5 回答 5

7

您的问题不会通过显式删除对象来解决......基本上是因为在 Java 中没有办法做到这一点。

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

  • 回收的对象可能需要“清理”(归零)。
  • 设计不佳的对象池可能会导致内存泄漏。
  • 设计不佳的对象池可能是并发瓶颈。
  • 设计不佳的对象池会增加 GC 开销,尤其是当您使用太小的堆运行时。

另一方面,您真正的问题可能是您的堆对于您尝试运行的应用程序来说太小了。如果你跑得太接近极限,GC 每次都不会回收很多垃圾。由于运行 GC 的成本与 NON-garbage 的数量成正比,因此很容易看出,随着堆接近满,GC 的效率是非线性的。

于 2012-04-10T07:04:30.047 回答
4

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

于 2012-04-10T06:39:30.663 回答
2

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

也就是说,当一个对象变得无法访问时,垃圾收集器会销毁该对象并释放相关的内存。

我阅读了编辑,也许您可​​以使用 byte[] 缓冲池解决您的问题。所以垃圾收集器不需要一直对缓冲区进行垃圾处理。

私有 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
  }

  }

于 2012-04-10T06:36:29.730 回答
1

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

于 2012-04-10T06:42:43.830 回答
1

Java 中没有“等价”运算符。系统在后台执行垃圾回收。没有显式的方法调用可以保证立即释放内存。

于 2012-04-10T06:46:44.323 回答