Java HeapDump分析:String还是StringBuilder,应该用什么?
Java HeapDump Analysis: String or StringBuilder, what should be used?
在我的应用程序中有一个堆转储,令人惊讶的是 char[]
保留的堆大约为 700MB,这很奇怪(至少对我而言)。同时String
只有150MB。
在我的应用程序中,我只使用了 StringBuilder
(使用默认的 StringBuilder
构造函数)并在我们追加数据时尽量避免使用 String
。
我的问题是:我们应该一直选择 StringBuilder
吗?如果是,我们如何减少它保留的堆?
可能您可以使用 StringInterner,它采用 StringBuilder 来避免创建对象 needlessly.You 首先用文本填充回收的 StringBuilder,如果与该文本匹配的字符串在内部,则返回该字符串(或StringBuilder 的 toString() 是。)好处是您只在看到新的字符串(或至少一个不在数组中的字符串)时创建对象(并且不会超过需要的对象)这可以获得 80% 到 99% 的命中率在加载许多数据字符串时显着降低内存消耗(和垃圾)。
是的,在构建字符串时总是选择 StringBuilder
- 这是连接字符串的最有效但仍然方便的方法。
听起来好像有很多 StringBuilder
等待被垃圾收集。但是,为了减少堆使用,您可以安全地 重用 您的 StringBuilder
,即使它们不是线程安全的,通过 Threadlocal
每个线程使用一个 StringBuilder
:
private static final ThreadLocal<StringBuilder> LOCAL_STRING_BUILDER =
ThreadLocal.withInitial(StringBuilder::new);
用法示例:
public String logMessage() {
StringBuilder sb = LOCAL_STRING_BUILDER.get();
sb.setLength(0); // Only resets the pointer to start. Doesn't affect the backing array
sb.append("foo=").append(myField); //etc
return sb.toString();
}
您最多只能拥有与线程一样多的 StringBuilder
,不会 那么 很多(可能是 10 到 100 条)。
仅供参考 StringBuilder
用于手动连接字符串;这行源码:
String str3 = str1 + str2;
被编译为:
String str3 = new StringBuilder().append(str1).append(str2).toString();
在我的应用程序中有一个堆转储,令人惊讶的是 char[]
保留的堆大约为 700MB,这很奇怪(至少对我而言)。同时String
只有150MB。
在我的应用程序中,我只使用了 StringBuilder
(使用默认的 StringBuilder
构造函数)并在我们追加数据时尽量避免使用 String
。
我的问题是:我们应该一直选择 StringBuilder
吗?如果是,我们如何减少它保留的堆?
可能您可以使用 StringInterner,它采用 StringBuilder 来避免创建对象 needlessly.You 首先用文本填充回收的 StringBuilder,如果与该文本匹配的字符串在内部,则返回该字符串(或StringBuilder 的 toString() 是。)好处是您只在看到新的字符串(或至少一个不在数组中的字符串)时创建对象(并且不会超过需要的对象)这可以获得 80% 到 99% 的命中率在加载许多数据字符串时显着降低内存消耗(和垃圾)。
是的,在构建字符串时总是选择 StringBuilder
- 这是连接字符串的最有效但仍然方便的方法。
听起来好像有很多 StringBuilder
等待被垃圾收集。但是,为了减少堆使用,您可以安全地 重用 您的 StringBuilder
,即使它们不是线程安全的,通过 Threadlocal
每个线程使用一个 StringBuilder
:
private static final ThreadLocal<StringBuilder> LOCAL_STRING_BUILDER =
ThreadLocal.withInitial(StringBuilder::new);
用法示例:
public String logMessage() {
StringBuilder sb = LOCAL_STRING_BUILDER.get();
sb.setLength(0); // Only resets the pointer to start. Doesn't affect the backing array
sb.append("foo=").append(myField); //etc
return sb.toString();
}
您最多只能拥有与线程一样多的 StringBuilder
,不会 那么 很多(可能是 10 到 100 条)。
仅供参考 StringBuilder
用于手动连接字符串;这行源码:
String str3 = str1 + str2;
被编译为:
String str3 = new StringBuilder().append(str1).append(str2).toString();