`
clarkht
  • 浏览: 39416 次
  • 性别: Icon_minigender_1
  • 来自: 岳阳
文章分类
社区版块
存档分类
最新评论

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

阅读更多
今天下午在看那个林信良的个人网站http://caterpillar.onlyfun.net/Gossip/中的字符串时,我留意下了他留下的Reference Site http://www.javablogging.com/string-and-memory-leaks/ 上面有一篇文章是关于 String.subString看法的,标题是“String and memory leaks”
  里面提及到http://nflath.com/2009/07/the-dangers-of-stringsubstring/上关于SubString造成内存泄漏的问题,这篇文章写的很不错。
恩,里面讲到了关于String.subString的本质.在Java中,字符串是很复杂的一个问题,java有对字符串的优化,比如String Pool. 对于SubString这个问题上, java也有自己的想法,比如
 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/ 上的列子:
 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!) 怎么办:                                            
String sub = new String( oldString.substring(0, 4) );
http://www.javablogging.com/string-and-memory-leaks/上举的例子很贴切:
引用
 public final static String START_TAG = "<title>";
public final static String END_TAG = "</title>";

public static String getPageTitle(String pageUrl) {
    // retrieve the HTML with a helper function:
    String htmlPage = getPageContent(pageUrl);

    // parse the page content to get the title
    int start = htmlPage.indexOf(START_TAG);
    start = start + START_TAG.length();
    int end = htmlPage.indexOf(END_TAG);
    String title = htmlPage.substring(start, end);
    return title;
} 

   直接引用作者的文字,实在是很平直,犀利啊
引用
    Now, try to imagine that the htmlPage String is huge – more than 100.000 characters, but the title of this page has only 50 characters. Because of the optimization mentioned above the returned object will reuse the char array of the htmlPage instead of creating a new one… and this means that instead of returning a small string object you get back a huge String with 100.000 characters array!! If your code will invoke getPageTitle() method many times you may find out that you have stored only a thousand titles and already you are out of memory!! Scary, right?

Of course there is an easy solution for that – instead of returning the title in line 13, you can return new String(title). The String(String) constructor is always doing a subcopy of the underlying char array, so the created title will actually have only 50 characters. Now we are safe:)

So what is the lesson here? Always use new String(String)? No… In general the String optimizations are really helpful and it is worth to take advantage of them. You just have to be careful with what you are doing and be aware of what is going on ‘under the hood’ of your code. String class API is in some situations not intuitive, so beware! (or just read trough it at least once:D)
分享到:
评论

相关推荐

    理解java中的字符串的内存分配

    ### 理解Java中的字符串内存分配 #### 概述 在Java中,字符串是一种非常重要的数据类型,广泛应用于各种程序开发场景之中。对于开发者来说,深入理解字符串的内存分配机制不仅能帮助他们写出更高效的代码,还能...

    java朗读中文字符串.zip

    总的来说,"java朗读中文字符串.zip"中的示例可能涵盖了以上这些知识点,通过阅读和学习这些代码,你可以了解如何在Java环境中实现中文文本的语音合成。对于学习和开发涉及语音交互的Java应用,这是一个非常实用的...

    基于Java中字符串内存位置详解

    在Java编程语言中,字符串(String)是一个特殊的数据类型,其内存位置的理解对于深入理解JVM(Java虚拟机)的工作原理至关重要。本文将详细探讨Java中字符串在内存中的存储位置,并通过实例进行验证。 首先,我们...

    JNI传递中文字符串资料

    在C/C++中,我们需要使用JNI的`GetStringChars`或`GetByteArrayElements`获取Java字符串的字节表示。由于Java字符串是UTF-16编码,因此,处理中文字符时,我们通常需要以宽字符(wchar_t)形式处理,或者先解码为...

    提取Java文件中包含的字符串

    在Java编程中,提取文件中的特定字符串是一项常见的任务,尤其在进行日志分析、代码审查或者数据挖掘时。本文将详细讲解如何通过Java的IO流技术来实现这一目标,特别是针对Java源代码文件(.java)的情况。 首先,...

    java 字符串内存分配的分析与总结(推荐)

    本文将深入探讨Java字符串内存分配的机制,以便更好地理解它们在程序运行时的行为。 首先,我们要明确Java中的字符串有两种主要的创建方式:直接赋值和使用`new`关键字。例如: 1. `String a = "123";` 2. `String...

    java内存泄漏解决

    在Java开发过程中,经常会遇到内存泄漏的问题,尤其是在长时间运行的应用程序中更为常见。本文将详细介绍如何解决Java内存泄漏问题,帮助开发者更好地理解和应对这一挑战。 #### 二、Java内存模型与内存区域 Java...

    java连接数据库字符串

    ### Java连接数据库字符串详解 #### 一、JDBC概述与加载驱动 在Java开发中,JDBC(Java Database Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类...

    详细介绍Java的内存管理与内存泄露

    4. **非显式的内存泄露**:除了显式地保留对对象的引用外,还有一些不太直观的情况也会导致内存泄露,比如日志类中对字符串的不当处理。 #### 示例分析 1. **循环添加对象至集合**: ```java Vector v = new ...

    Android Java代码与JNI交互字符串转换(四)

    在JNI中,使用`NewStringUTF()`创建的字符串和`GetStringUTFChars()`返回的字节数组,需要在使用后手动释放,避免内存泄漏。使用`DeleteLocalRef()`来释放本地引用。 3. **JNI中的字符串操作**: - JNI中的字符串...

    基于freetts的java朗读字符串

    6. **释放资源**:在完成朗读任务后,记得释放`Voice`对象,以防止内存泄漏。这可以通过调用`voice.shutdown()`来完成。 除了基础的文本转语音功能,Freetts还提供了许多高级特性,例如支持多种语言(如英语、法语...

    字符串的哈希Key算法

    在开发过程中,结合字符串哈希Key算法和内存监控类,可以优化程序性能,防止因内存问题导致的程序崩溃,同时也能提升程序的可维护性和稳定性。然而,设计和实现这样的工具需要考虑各种因素,例如哈希冲突的解决、...

    Java中堆内存与栈内存分配浅析

    Java编程语言将内存划分为两种...总的来说,理解Java中的堆和栈内存分配机制对于优化代码性能和避免内存泄漏至关重要。开发者需要根据实际需求合理地使用栈和堆,平衡性能和内存消耗,以实现更高效、更稳定的程序运行。

    JAVA内存溢出问题总结

    JAVA 内存溢出问题是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用的内存大于虚拟机能提供的最大内存。内存溢出问题可以从容器和程序类两个方面进行排查,容器问题可以调整容器参数来解决...

    字符串管理

    例如,Valgrind是一个内存检测工具,可以帮助我们发现字符串操作中的内存泄漏或越界访问。GDB是另一个强大的调试器,可以让我们逐行检查代码执行,观察字符串变量的变化。除此之外,代码分析工具如SonarQube可以检测...

    java核心 内存分配问题

    Java 内存分配是理解Java程序性能和...理解Java内存分配对于编写高效、无内存泄漏的代码至关重要,同时也对诊断和解决性能问题有着深远的影响。通过深入了解这些概念,开发者能够更好地设计和优化他们的Java应用程序。

    Java字符串的10个入门知识.docx

    ### Java字符串的10个入门知识详解 #### 一、基本数据类型与字符串之间的转换 在Java编程中,经常需要进行基本数据类型与字符串之间的相互转换。这些转换可以通过多种方式进行。 1. **基本数据类型转字符串** - ...

    string字符串解释

    理解字符串的内存管理对于避免内存泄漏和提高程序性能至关重要。 5. **字符串常量与变量**:字符串可以是常量(不可改变)或变量(可改变)。在C/C++中,字符串常量是字符数组的别名,而Java和Python则有特殊的字符...

    JAVA垃圾回收机制与内存泄露问题实用.pdf

    Java垃圾回收机制是Java语言的一个重要特性,它自动管理程序中的内存分配和释放,以防止内存泄漏和资源浪费。垃圾回收的核心思想是追踪并回收那些不再被程序引用的对象,释放其所占的内存空间,以便再次分配给其他...

Global site tag (gtag.js) - Google Analytics