Dan*_*Dan 9 java string memory-management pool flyweight-pattern
我的应用程序是多线程的,具有密集的字符串处理.我们正在经历过多的内存消耗,并且分析已经证明这是由于String数据.我认为使用某种flyweight模式实现甚至缓存可以大大节省内存消耗(我知道Strings经常是重复的,尽管我在这方面没有任何硬数据).
我查看了Java Constant Pool和String.intern,但它似乎可能引发一些PermGen问题.
在java中实现应用程序范围的多线程字符串池的最佳替代方法是什么?
编辑:另见我以前的相关问题:java如何实现引擎盖下的字符串的flyweight模式?
注意:此答案使用可能与现代运行时JVM库无关的示例.特别是,该substring示例不再是OpenJDK/Oracle 7+中的问题.
我知道它违背了人们经常告诉你的内容,但有时明确地创建新String实例可能是减少记忆的重要方法.
因为字符串是不可变的,所以有几种方法利用这一事实并共享后备字符数组以节省内存.但是,偶尔这可以通过防止垃圾收集这些数组的未使用部分来增加内存.
例如,假设您正在解析日志文件的消息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...
}
Run Code Online (Sandbox Code Playgroud)
但是看看实际存储的数据:
//...
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) );
Run Code Online (Sandbox Code Playgroud)
它是整个测试行,因为匹配器只是围绕相同的字符数据包装一个新的String实例.当您更换比较结果String id = matcher.group(1);用String id = new String(matcher.group(1));.
| 归档时间: |
|
| 查看次数: |
5712 次 |
| 最近记录: |