Ami*_*itG 13 java memory memory-leaks
据说substring
String类中的方法会导致内存泄漏.这是真的吗?怎么样?有什么替代方案吗?
特别是在寻找答案,
在java中可能导致内存泄漏的所有其他事情是什么?这将有助于我在编码时保持谨慎.
Den*_*ret 28
在以前的JDK版本中,该substring
方法的实现将构建一个新String
对象,保持对整个char数组的引用,以避免复制它.因此,您可能无意中仅使用一个字符串保留对非常大的字符数组的引用.这是一个可能导致错误的例子.
此方法现已更改,此"泄漏"不再存在.
如果你想使用一个旧的JDK(比OpenJDK 7更新,更新6)并且你想要使用最少的字符串substring
,请使用另一个字符串的构造函数:
String s2 = new String(s1.substring(0,1));
Run Code Online (Sandbox Code Playgroud)
关于你的第二个问题,关于"其他可能导致java中内存泄漏的事情",不可能以建设性的方式回答.在java标准库中没有很多实例可以很容易地保持对对象的隐藏引用.在一般情况下,请注意您构建的所有引用,可能是未清理的集合或外部资源(文件,数据库事务,本机窗口小部件等)中可能出现的最常见问题.
Bri*_*new 12
该substring()
方法不为a分配新的字符数组String
,而是简单地String
在现有的 char数组上生成带有窗口的a .这是一个flyweight模式的实现,并被视为一种优化.
因此,如果我有一个巨大的String
(字符数组),然后创建一个子字符串,即使我垃圾收集原始字符串,原始字符数组仍然存在(尽管你认为你有一个子字符串,比如2个字符).当(例如)解析大量输入数据流(可能是XML文件)并通过以下方式提取少量文本时,通常会遇到此问题substring()
使用看似冗余的String(String str)
构造函数(String
构造函数采用String
!)解决了这个问题,因为它分配了一个新的(可能更小的)char数组,允许原始文件被垃圾收集.
请注意,从Java 7u6开始,此行为已更改.
字符串子字符串可以导致保留比预期更多的内存.因此,这不是内存泄漏,因为这个内存可以正常恢复.
最简单的解决方案是使用最新版本的Java 7,它不会这样做.由于这是Oracle唯一免费支持的版本,因此无论如何都应该考虑这样做.
因此它在Java 7更新5中被"修复".恕我直言,它不是一个简化实现的修复.获取每个子字符串的副本需要更多的工作并且可能消耗更多的内存,但它确实意味着可以少担心一件事.
在java中可能导致内存泄漏的所有其他事情是什么?
任何对象都可以清理,因此无法在C/C++术语中创建内存泄漏.你能做的就是不正确地抓住物体.一个常见的例子是忘记关闭JDBC资源等资源.这可能会导致您以您不期望的方式保留内存.
在String对象中,当您调用时substring
,value
属性在两个字符串之间共享.
因此,如果从大字符串中获取子字符串并将其保留很长时间,则不会对大字符串进行垃圾回收.实际上,它可能导致内存泄漏.
归档时间: |
|
查看次数: |
18661 次 |
最近记录: |