强制显式删除 Java 对象

2022-09-03 16:45:27

我正在开发一个Java服务器,该服务器可以处理大量非常密集的流量。服务器接受来自客户端的数据包(通常为数 MB),并将其转发到其他客户端。服务器从不显式存储任何传入/传出数据包。然而,服务器不断遇到异常。OutOfMemoryException

我添加到服务器的消息传递组件中,希望内存能够释放。此外,我将 JVM 的堆大小设置为 1 GB。我仍然有很多例外。System.gc()

所以我的问题是:我如何确保兆字节消息不会无限期排队(尽管不需要)?有没有办法对这些对象调用“delete”来保证它们没有使用我的堆空间?

        try
        {
           while (true)
            {
               int r = generator.nextInt(100);//generate a random number between 0 and 100
                Object o =readFromServer.readObject();
                sum++;
                // if the random number is larger than the drop rate, send the object to client, else
                //it will be dropped
                if (r > dropRate)
                {
                    writeToClient.writeObject(o);
                    writeToClient.flush();
                    numOfSend++;
                    System.out.printf("No. %d send\n",sum);
                }//if

            }//while
        }//try

答案 1

对象流保存对从中写入/读取的每个对象的引用。这是因为序列化协议允许对流中较早出现的对象进行反向引用。您可能仍然可以使用此设计,但使用 writeUnshared/readUnshared 而不是 writeObject/readObject。我认为,但不确定,这将阻止流保留对对象的引用。

正如Cowan所说,这种方法在这里也起作用。最安全的做法可能是在写信时立即使用reset()writeUnsharedreset()ObjectOutputStream


答案 2

当 JVM 位于 的边缘时,它将运行 GC。OutOfMemoryError

因此,事先称自己为自己不会解决问题。问题要在其他地方解决。基本上有两种方法:System.gc()

  1. 编写内存高效代码和/或修复代码中的内存泄漏。
  2. 为 JVM 提供更多内存。

使用 Java Profiler 可能会提供有关内存使用情况和潜在内存泄漏的大量信息。

更新:根据您对导致此问题的代码的更多信息的编辑,请查看Geoff Reedy在本主题中的答案,其中建议使用ObjectInputStream#readUnshared()ObjectOutputStream#writeUnshared()代替。(链接的)Javadocs也很好地解释了这一点。