我是否需要担心字符串常量池?

时间:2008-10-10 10:18:01

标签: java string

我有一个非常庞大的Java应用程序 - 它需要大量不同的String对象。

我是否需要担心字符串常量池的内存和性能?

有什么方法可以看到游泳池在任何时候都有多大?

5 个答案:

答案 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);
    }