现在的位置: 首页 > 综合 > 正文

(转)Java中字符串与内存泄漏的问题

2013年08月18日 ⁄ 综合 ⁄ 共 1433字 ⁄ 字号 评论关闭
http://clarkht.iteye.com/blog/482644

String oldStr = "hello,clark"; 

String newStr = oldStr.subString(0,4);  

对于这个写法,实际上对于oldStr是一个char[]数组[h,e,l,l,0,,,c,l,a,r,k],对于subString操作,newStr并不是自己copy oldStr的char[]数组hello自己去创建一个新的char[]数组,而是java在背后进行了String Reusing Optimization,它不会自己创建一个新的char数组,而是reuse原来的char数组。所以了,这样就不会有很多的原来的char[]数组的碎片。引用http://www.javablogging.com/string-and-memory-leaks/ 上的列子:

Java代码 

public static void sendEmail(String emailUrl) { 

    String email = emailUrl.substring(7); // 'mailto:' prefix has 7 letters 

    String userName = email.substring(0, email.indexOf("@")); 

    String domainName = email.substring(email.indexOf("@")); 



 

public static void main(String[] args) { 

    sendEmail("mailto:user_name@domain_name.com"); 

}  

但是这个虽然在一般情况是好,不过也是有代价的。根据http://nflath.com/2009/07/the-dangers-of-stringsubstring/上,因为字符串不是自己新建一个char[]数组,而是引用了原来的char[]数组,这样oldStr就无法garbage collected ,因为newStr还是拥有oldStr的char[]数组的引用。这样容易引起Outof Memory 异常。解决办法是了,便是让newStr拥有自己的char[]数组,也就是自己在subString时强迫创建自己的char[]数组,这样就不会有garbage collected 的问题(reachable but unused!) 怎么办:                                           

Java代码 

String sub = new String( oldString.substring(0, 4) ); 

---------------------------------------------------------------

为了避免内存拷贝、加快速度,Sun JDK直接复用了原String对象的char[],偏移量和长度来标识不同的字符串内容。也就是说,subString出的来String小对象仍然会指向原String大对象的char[],split也是同样的情况 。这就解释了,为什么HashMap中String对象的char[]都那么大。

-------------------------------------------------------

可以参考:

http://jarfield.iteye.com/blog/583946

抱歉!评论已关闭.