字符串连接和内存泄漏

时间:2013-12-30 11:53:57

标签: java

我们几乎到处都使用串联字符串进行记录 例如:catch (Exception e) { logger.error("setUserSession()" + e.getMessage()); } 但我们怀疑这些语句是否会因字符串突变而导致内存泄漏。有人建议使用String builder。但是我从像StringBuilder vs String concatenation in toString() in Java这样的讨论中理解的是Java Compiler将使用String builder来转换字符串连接。

为了测试这个,我尝试反编译以下java代码(使用JD-GUI);

    logger.error("string1" + "string2");
    logger.error("setUserSession()" + e.getMessage());

反编译器生成以下代码;

    logger.error("string1string2");
    logger.error("setUserSession()" + e.getMessage());

但是我期待第二个语句中的String builder,如;

logger.error(new StringBuilder().append("setUserSession()").append(e.getMessage());

所以我有两个疑问:

  1. 字符串连接实际上是否会造成如此多的内存泄漏?
  2. 或者我是否需要明确使用字符串构建器 - >将我的字符串附加到字符串构建器 - >然后使用字符串构建器删除功能删除字符串构建器?
  3. Java编译器使用“字符串”构建器转换简单字符串连接。 (我们可以使用反编译器工具来检查它吗?)

2 个答案:

答案 0 :(得分:6)

  1. 它不会造成内存泄漏。它将创建内存使用,但垃圾收集器将整理它。
  2. 除非您的字符串连接分布在多个语句中,否则无需显式使用StringBuilder
  3. 我认为你对Java有误解。这些对象是StringObjectMyObject还是其他任何内容都无关紧要。只要对它的所有强引用都超出范围,对象就有资格进行垃圾收集,并在适当的时候回收使用的内存。

    在Java中泄漏内存的唯一方法是泄漏资源(例如打开流,创建线程等)或者意外地保留对某些内容的引用(例如将其添加到List并且永远不会从List中删除它)。

答案 1 :(得分:0)

最好在日志语句之前检查是否启用了日志级别,如下所示:

if(logger.isErrorEnabled()) {

    //At runtime while executing below statement,Java creates "String1" and "String2"
    //String objects in the string pool regardless of the log level
    logger.error("string1" + "string2");
}

这可以防止在字符串池中不必要地创建“String1”和“String2”对象,尽管日志记录语句不执行任何操作。(如果日志级别比ERROR更大)