我正在应用程序中寻找内存错误,它似乎与 ServerSocketChannel.accept() 生成的 byte[] 缓冲区有关。根据 jvisualvm 的说法,在应用程序使用的 505 兆内存中,超过 90% 的内存被 byte[] 数组使用。进一步跟踪,有 68k+ 个 byte[] 实例,到目前为止最常见的大小是 16681。
我对这些字节数组进行了随机采样,它们无一异常(exception)都与 InputRecord 或 OutputRecord 相关。如果我遵循所有引用,我找不到任何不返回终结器的引用,以我有限的理解,这意味着该对象已准备好被垃圾收集,但由于某种原因或其他原因尚未准备好.
我希望可以附上 jvisualvm 输出的屏幕截图。无论如何,所指对象包括:
- 输入记录
- 应用程序输入流
- SSLSocketImpl
- SocketInputStream
- SocksSocketImpl
- SocketOutputStream
- AppOutputStream
- 委托(delegate)HttpsURLConnection
- HttpsURLConnectionImpl
这似乎只发生在使用 Apple VM 的客户身上。有人知道为什么这些缓冲区没有被垃圾收集吗?我读取的堆配置文件是否错误?黑客攻击还是解决方法?
最佳答案
finalize
在垃圾收集器发现对象后的某个时间调用。 Sun 实现与 java.lang.ref 混合在一起。正确关闭资源应该释放它们的内存。如果具有 finalize
的对象在关闭时无法清空对缓冲区的引用,那么这些缓冲区将一直挂起,直到执行终结器后相关的 GC。
尽管规范允许有多个终结器线程,但通常只有一个终结器线程。如果由于阻塞操作、不适当的持有锁或其他原因而阻塞,则可终结对象的 GC 将被阻止。我建议检查 VisualVM 中的终结器线程,看看它是否被阻塞。
关于Java 服务器套接字缓冲区在 Mac 上没有被垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/865951/