Java 标准 API 中的内存泄漏陷阱

2022-08-31 20:36:45

Java 标准 API 的哪些类在以(不明显)不正确的方式使用时会导致内存泄漏?如何避免/修复这些内存泄漏?

示例:并保留对它们所看到的所有对象的引用,以便将同一对象的后续事件作为引用而不是副本发送(从而处理循环引用)。当您无限期地保持此类流打开时(例如,使用它通过网络进行通信时),这会导致内存泄漏。ObjectInputStreamObjectOutputStream

修复:定期调用 reset() 或在每个顶级对象之后调用 reset()。


答案 1

一个很大的问题是,获取Java字符串的子字符串是指原始字符串。

示例:您读取 3000 个字符的记录并获取 12 个字符的子字符串,并将其返回给调用方(在同一 JVM 中)。即使您没有直接引用原始字符串,该 12 个字符的字符串仍在内存中使用 3000 个字符。

对于接收然后解析大量消息的系统,这可能是一个真正的问题。

您有几种方法可以避免这种情况:

String sub = new String(str.substring(6,12));

String sub = str.substring(6,12).intern();

第一个是更清晰的。第二个还有其他含义,因为你使用的是PermGen空间。过度使用,除非向 VM 提供足够的 VM,否则可能会耗尽。

请记住,这只有在你拿走小子字符串然后扔掉原始字符串并且你正在做很多事情时才有意义。


答案 2

您注册为事件接收者的所有内容(例如在 GUI 框架中)只要已注册且事件源处于活动状态,就无法进行垃圾回收。

如果开发人员不知道从事件源到事件订阅服务器的强引用,则可能会引入内存泄漏。


推荐