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

问题描述:

我有一个非常繁重的Java应用程序 - 它需要大量不同的String对象的提要。我是否需要担心字符串常量池?

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

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

+0

对于sun的jvm,请使用jmap -permstat来查看interned字符串使用了多少内存 – Ron 2010-09-09 17:33:18

正如马里奥说,常量池仅仅是实习生有关()的字符串,并且是常量字符串在java代码中(这些都是隐式实现的)。

但有一个可能适用于你的情况更告诫: 的substring()方法将共享底层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 

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

+0

不错,我不知道那个警告。这个包构造函数将char []作为参数并保存强引用。那么,如果我们真的只需要一个子字符串的副本,该怎么办? – 2008-10-10 11:20:53

我想你应该剖析你的应用程序,无论是否有实习。然后你会看到究竟是什么效果。

我不相信有一种方法可以查看字符串常量池的大小。

如果它是对象的提要,那么除非您调用intern(),否则它们不会进入String常量池,据我所知。 Interned字符串的内存消耗不是来自Heap,而是来自Perm Gen内存空间,因此如果实习大量字符串,应用程序将与OutOfMemory一起崩溃,即使剩下大量Heap也是如此。

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

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

您可以使用此标志会增加PermSize如果您运行的内存:

-XX:MaxPermSize=64m 

不知道程序是什么,我只能建议你尝试使用字符串作为流,并且不存储字符串作为整体。也许你需要为你的应用程序进行更多的抽象,并且创造一个更高效的内存表示?

在Java 1.7串() - 方法不再使用相同的字符[]相反,它是子串复制到新的数组即

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

其中所有的String构造如果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); 
    }