String类中的substring方法导致内存泄漏

据说String类中的substring方法会导致内存泄漏。 这是真的吗? 怎么样? 有什么替代方案吗?
特别是寻找答案,
在java中可能导致内存泄漏的所有其他事情是什么? 这将有助于我在编码时保持谨慎。

在以前版本的JDK中, substring方法的实现将构建一个新的String对象,保持对整个char数组的引用,以避免复制它。 因此,您可能无意中仅使用一个字符串保留对非常大的字符数组的引用。 这是一个可能导致错误的例子 。

此方法现已更改,此“泄漏”不再存在。

如果你想使用一个旧的JDK(比OpenJDK 7更新,更新6)并且你希望在substring之后拥有最少的字符串,那么使用另一个字符串的构造函数:

 String s2 = new String(s1.substring(0,1)); 

至于你的第二个问题,关于“其他可能导致java内存泄漏的事情”,不可能以建设性的方式回答。 在java标准库中没有很多实例可以很容易地保持对对象的隐藏引用。 在一般情况下,请注意您构建的所有引用,可能是未清除的集合或外部资源(文件,数据库事务,本机窗口小部件等)中可能出现的最常见问题。

substring()方法不为String分配新的字符数组,而只是生成一个带有现有 char数组窗口的String 。 这是一个flyweight模式的必要条件,并被视为一种优化。

因此,如果我有一个巨大的String (char数组),然后创建一个子字符串,即使我垃圾收集原始字符串,原始字符数组仍然存在(尽管你认为你有一个子字符串,比如2个字符)。 当(例如)解析大量输入数据流(可能是XML文件)并通过substring()提取少量文本时,通常会遇到此问题

使用看似冗余的String(String str)构造函数(采用String构造函数!)解决了这个问题,因为它分配了一个新的(可能更小的)char数组,允许对原始文件进行垃圾回收。

请注意,从Java 7u6开始,此行为已更改。

字符串子字符串可以导致保留比预期更多的内存。 因此,这不是内存泄漏,因为这个内存可以正常恢复。

最简单的解决方案是使用最新版本的Java 7,它不会这样做。 由于这是Oracle唯一免费支持的版本,因此无论如何都应该考虑这样做。

因此它在Java 7更新5中被“修复”。恕我直言,它不是一个简化实现的修复。 获取每个子字符串的副本需要更多的工作并且可能消耗更多的内存,但这确实意味着可以少担心一件事。

在java中可能导致内存泄漏的所有其他事情是什么?

任何对象都可以清理,因此无法在C / C ++术语中创建内存泄漏。 你能做的就是不正确地抓住物体。 一个常见的例子是忘记关闭JDBC资源等资源。 这可能会导致您以您不期望的方式保留内存。

在String对象中,当您调用substringvalue属性在两个字符串之间共享。

因此,如果从大字符串中获取子字符串并将其保留很长时间,则不会对大字符串进行垃圾回收。 实际上,它可能导致内存泄漏。