[英]Do I need to worry about the String Constant Pool?
我有一个非常庞大的Java应用程序 - 它需要大量不同的String对象。
我是否需要担心字符串常量池的内存和性能?
有什么方法可以看到游泳池在任何时候都有多大?
正如Mario所说,常量池只与intern()ed字符串相关,而且与java代码中的常量字符串相关(这些是隐式实现的)。
但是还有一个警告可能适用于您的情况: substring()
方法将与原始String共享底层char[]
。 所以模式
String large = ... // read 10k string
String small = large.substring(...) // extrakt a few chars
large = null; // large String object no longer reachable,
// but 10k char[] still alive, as long as small lives
可能会导致意外的内存使用
如果它是对象的提要,那么除非你调用intern(),否则它们不会进入String常量池,据我所知。 实习字符串的内存消耗不是来自Heap,而是来自Perm Gen内存空间,因此如果您实施了很多字符串,应用程序将与OutOfMemory崩溃,即使剩下很多堆也是如此。
因此,除非您实习所有这些字符串,否则不应该关注它。 如果它成为一个问题,可以有自己的Map实现来存储这些字符串,所以你不使用内部机制。
我检查了intern()方法的实现,它是本机的,因此测量内存消耗或查看池的内容似乎并不简单。
如果内存不足,可以使用此标志来增加PermSize:
-XX:MaxPermSize=64m
我认为无论有无实习,都应该对您的应用进行分析。 然后,您将看到确切的效果。
我不相信有一种方法可以看到字符串常量池的大小。
我不知道程序究竟是什么,我只能建议您尝试将字符串用作流,并且不存储字符串作为整体。 也许你需要为你的应用程序做更多的抽象,并发明一个内存效率更高的中间表示?
在Java 1.7 substring()中 - 方法不再使用相同的char []而是将子字符串复制到新的数组中,即
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
如果beginIndex不为零或endIndex不等于char []数组的长度,则全部为String构造函数。
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.