Java Standard API中的内存泄漏陷阱

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

示例: ObjectInputStreamObjectOutputStream保留对所有对象的引用,以便将随后发生的同一对象作为引用而不是副本发送(从而处理循环引用)。 这会导致内存泄漏,当你保持这样一个stream无限期打开(例如,当使用它来通过networking进行通信)。

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

一个重要的问题是获取Javastring的子string是指原始string。

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

对于接收并parsing大量消息的系统,这可能是一个真正的问题。

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

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

要么

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

第一个更清楚。 第二个有其他的含义,因为你使用的是PermGen空间。 过度使用,你可以用尽,除非你足够的虚拟机。

请记住,这只有在你使用小的子串,然后扔掉原来的string,而且你做了很多。

只要注册并且事件源处于活动状态,您注册为事件接收者的所有东西(例如GUI框架)都不能被垃圾回收。

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

任何非静态的内部类你坚持外部类。 这样看起来天真无邪的内部类可以保存一个巨大的对象图。 将实例放在静态或应用程序范围内的某个集合中,并且使用大量不应该使用的内存。

Thread的每个实例都为堆栈分配内存(默认为512k,可通过-Xss )。 这不是一个泄漏,但是对一个应用程序进行大量multithreading的天真尝试将导致相当大的非显而易见的内存消耗。

任何类与dispose()方法?

例如java.awt.Window#dispose :

public void dispose ()

释放此窗口,其子组件及其所有子项使用的所有本机屏幕资源。 也就是说,这些组件的资源将被销毁,它们消耗的所有内存将被返回到操作系统,并被标记为不可显示。

使用强引用时,弱引用就足够了。 执行自己的状态和资源pipe理的应用程序和API是这里通常的罪魁祸首。

然后,观察者模式的使用可能导致内存泄漏 – 当观察者从主体中除去自身时,除非主体还释放对观察者/监听者的引用,否则内存不能被回收。 前面已经指出了这一点,但是没有多less人意识到即使是伐木者也是观察者。

此外, 还有类的可能性,其实例化的对象会自动放入静态成员中 。 有些类甚至没有release()或者dispose()方法,所以引用继续被静态成员持有。 这种内存泄漏最终会导致出现OutOfMemory错误,并以PermGen空间问题为根本原因报告,从而使诊断更加困难。