当前位置:  开发笔记 > 编程语言 > 正文

Java Standard API中的内存泄漏陷阱

如何解决《JavaStandardAPI中的内存泄漏陷阱》经验,为你挑选了4个好方法。

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

示例: ObjectInputStreamObjectOutputStream保留对他们所见过的所有对象的引用,以便发送与引用相同的对象的后续出现而不是副本(从而处理循环引用).当您无限期地保持此类流(例如,当使用它通过网络进行通信时)时,这会导致内存泄漏.

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



1> cletus..:

一个重要的问题是获取Java字符串的子字符串是指原始字符串.

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

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

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

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

要么

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

第一个是更明确的.第二个有其他影响,因为你正在使用PermGen空间.过度使用你可能会用完,除非你给你足够的VM.

请记住,这只有在您使用小的子串然后丢弃原始字符串并且您正在执行此操作时才有意义.


+1:我会说这是陷入JDK的最大"陷阱"之一......让我长时间地确定这是我的webcrawler漏掉它看到的每个页面的整个HTML源码的原因.说真的,Sun/Oracle ......如果你有这种严重的"优化"副作用,至少在[文档]中说些什么(http://docs.oracle.com/javase/6/文档/ API /爪哇/郎/ String.html#子(INT))
@Murat:碰到旧评论:因为它在内部引用与原始字符串相同的char数组,只是具有不同的偏移量和长度.如果你创建了很多重叠的子串,它实际上节省了内存.
我检查了String #substring的源代码,它将创建一个新的String并复制内部char []的范围.我正在使用jdk7,也许这是固定的?

2> Black..:

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

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



3> krosenvold..:

您使用的任何非静态内部类都保留在外部类中.因此,无辜的内部类可以保持一个巨大的对象图.将实例放在某个静态或应用程序范围的集合中,并且您正在使用大量不应该使用的内存.



4> Brian Agnew..:

线程的每个实例化都为堆栈分配内存(默认为512k,可调整通道-Xss).这不是一个泄漏这样的,但天真的企图大量多线程的应用程序将导致内存相当大的非显而易见的消耗.


实际上,如果您创建Thread对象并且从不调用start(),它可能会变成彻底的泄漏 - 然后堆栈内存永远不会被回收,IIRC.
@Michael Borgwardt:我不认为是这样的; 你有资源吗?\ [edit \]:看起来它可能是旧版本JVM中的一个错误,但应该在Java 5中修复.
推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有