我有一个非常庞大的Java应用程序 - 它需要大量不同的String对象。
我是否需要担心字符串常量池的内存和性能?
有什么方法可以看到游泳池在任何时候都有多大?
答案 0 :(得分:4)
正如Mario所说,常量池只与intern()ed字符串相关,而且与java代码中的常量字符串相关(这些是隐式实现的。)
但还有一个警告可能适用于您的案件:
substring()
方法将与底层char[]
共享。{1}}
原始字符串。所以模式
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
可能会导致意外的内存使用。
答案 1 :(得分:3)
如果它是对象的提要,那么除非你调用intern(),否则它们不会进入String常量池,据我所知。实习字符串的内存消耗不是来自Heap,而是来自Perm Gen内存空间,所以如果你实习很多字符串,应用程序将会崩溃OutOfMemory,即使剩下很多堆。
所以除非你实习所有这些字符串,否则它不应该是一个问题。如果它成为一个问题,可以有自己的Map实现来存储这些字符串,所以你不使用内部机制。
我检查了intern()方法的实现,它是原生的,因此测量内存消耗或查看池的内容似乎并不简单。
如果内存不足,可以使用此标志来增加PermSize:
-XX:MaxPermSize=64m
答案 2 :(得分:1)
我认为你应该在有或没有实习的情况下描述你的应用程序。然后,您将看到确切的效果。
我不相信有办法看到字符串常量池的大小。
答案 3 :(得分:0)
我不知道程序究竟是什么,我只能建议您尝试将字符串用作流,并且不要将字符串存储为整体。也许你需要为你的应用程序做更多的抽象,并发明一个更节省内存的中间表示?
答案 4 :(得分:0)
在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);
}