我的应用程序是多线程的,具有密集的字符串处理。我们遇到内存消耗过多的情况,分析表明这是由字符串数据引起的。我认为使用某种享元模式实现甚至缓存会极大地提高内存消耗(我确信字符串经常是重复的,尽管我在这方面没有任何硬数据)。
我研究过 Java Constant Pool 和 String.intern,但似乎它会引发一些 PermGen 问题。
在 java 中实现应用程序范围的多线程字符串池的最佳替代方案是什么?
编辑:另请参阅我之前的相关问题:java 如何在幕后实现字符串的享元模式? https://stackoverflow.com/questions/2909848
注意:此答案使用的示例可能与现代运行时 JVM 库不相关。特别是,substring
在 OpenJDK/Oracle 7+ 中示例不再是问题。
我知道这与人们经常告诉你的相反,但有时会明确地创造新的String
实例can是减少记忆力的重要方法。
由于字符串是不可变的,因此有几种方法利用这一事实并共享支持字符数组以节省内存。但是,有时这实际上可以通过防止对这些数组的未使用部分进行垃圾收集来增加内存。
例如,假设您正在解析日志文件的消息 ID 以提取警告 ID。你的代码看起来像这样:
//Format:
//ID: [WARNING|ERROR|DEBUG] Message...
String testLine = "5AB729: WARNING Some really really really long message";
Matcher matcher = Pattern.compile("([A-Z0-9]*): WARNING.*").matcher(testLine);
if ( matcher.matches() ) {
String id = matcher.group(1);
//...do something with id...
}
但看看实际存储的数据:
//...
String id = matcher.group(1);
Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
char[] data = ((char[])valueField.get(id));
System.out.println("Actual data stored for string \"" + id + "\": " + Arrays.toString(data) );
这是整个测试行,因为匹配器只是将新的 String 实例包装在相同的字符数据周围。更换时比较结果String id = matcher.group(1);
with String id = new String(matcher.group(1));
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)