Java 我需要担心字符串常量池吗?

Java 我需要担心字符串常量池吗?,java,string,Java,String,我有一个非常重字符串的Java应用程序,它需要大量不同的大字符串对象 我需要担心字符串常量池的内存和性能吗 有什么办法可以看出在任何时候人才库有多大?我认为你应该分析一下你的申请,无论是否有实习。然后您将确切地看到效果是什么 我不相信有办法查看字符串常量池的大小。据我所知,如果它是对象的馈送,那么它们不会进入字符串常量池,除非调用intern()。插入字符串的内存消耗不是来自堆,而是来自Perm Gen内存空间,因此,如果插入大量字符串,应用程序将因OutOfMemory而崩溃,即使还有大量堆

我有一个非常重字符串的Java应用程序,它需要大量不同的大字符串对象

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


有什么办法可以看出在任何时候人才库有多大?

我认为你应该分析一下你的申请,无论是否有实习。然后您将确切地看到效果是什么


我不相信有办法查看字符串常量池的大小。

据我所知,如果它是对象的馈送,那么它们不会进入字符串常量池,除非调用intern()。插入字符串的内存消耗不是来自堆,而是来自Perm Gen内存空间,因此,如果插入大量字符串,应用程序将因OutOfMemory而崩溃,即使还有大量堆

所以这不应该是一个问题,除非你正在实习所有这些字符串。如果这成为一个问题,您可以使用自己的映射实现来存储这些字符串,因此您不需要使用内部机制

我检查了intern()方法的实现,并且它是本机的,因此测量内存消耗或查看池的内容似乎并不简单

如果内存不足,可以使用此标志来增加PermSize:

-XX:MaxPermSize=64m

正如Mario所说,常量池只与intern()插入的字符串以及java代码中的常量字符串相关(这些字符串是隐式插入的)

但还有一个警告可能适用于您的案例:
substring()
方法将与 原始字符串。那么模式呢

  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

可能会导致意外的内存使用。

由于不知道程序是什么,我只能建议您尝试将字符串作为流使用,而不是将字符串作为一个整体存储。也许你需要为你的应用程序做更多的抽象,并发明一种更节省内存的中间表示法?

在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);
    }
公共字符串子字符串(int-beginIndex,int-endIndex){
如果(beginIndex<0){
抛出新的StringIndexOutOfBoundsException(beginIndex);
}
if(endIndex>value.length){
抛出新的StringIndexOutOfBoundsException(endIndex);
}
int SUBELN=endIndex-beginIndex;
如果(子项<0){
抛出新StringIndexOutOfBoundsException(SubCN);
}
返回((beginIndex==0)和(&(endIndex==value.length))?此
:新字符串(值、beginIndex、子项);
}
如果beginIndex不为零或endIndex不等于char[]数组的长度,则所有字符串都将被转换为字符串构造函数

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);
    }
公共字符串(字符值[],整数偏移量,整数计数){
如果(偏移量<0){
抛出新StringIndexOutOfBoundsException(偏移量);
}
如果(计数<0){
抛出新StringIndexOutOfBoundsException(计数);
}
//注意:偏移量或计数可能接近-1>>>1。
如果(偏移量>value.length-计数){
抛出新StringIndexOutOfBoundsException(偏移量+计数);
}
this.value=Arrays.copyOfRange(值、偏移量、偏移量+计数);
}

不错,我不知道这个警告。有一个包构造函数将char[]作为参数并保存强引用。那么,如果我们真的只想得到子字符串的副本,该怎么办呢?String small=new String(large.substring(…))对于sun的jvm,使用jmap-permstat查看内部字符串使用了多少内存