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

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

你可能感兴趣的:((转)Java中字符串与内存泄漏的问题)