2008-10-10 5 views
2

J'ai une application Java qui est très encombrante - elle nécessite un grand nombre de gros objets String différents.Dois-je m'inquiéter de la piscine à cordes Constant?

Ai-je besoin de m'inquiéter à propos du pool constant de chaînes pour la mémoire et les performances?

Existe-t-il un moyen de voir la taille de la piscine à tout moment?

+0

pour le jvm de soleil, l'utilisation jmap -permstat pour voir la quantité de mémoire utilisée par les chaînes internées – Ron

Répondre

4

Comme Mario dit, la piscine constante ne concerne que stagiaire() ed chaînes, et des chaînes qui sont des constantes dans le code Java (ceux-ci sont implicitement internés).

Mais il y a une mise en garde plus que pourrait appliquer à votre cas: La méthode substring() partagera les char[] sous-jacente à la chaîne d'origine. Le motif

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 

peut provoquer une utilisation inattendue de la mémoire.

+0

un Nice, je ne savais pas cette mise en garde. Il y a ce constructeur de paquet qui prend le caractère [] comme argument et contient la référence forte. Alors que faire si nous voulons vraiment une copie de seulement la sous-chaîne? –

+0

Chaîne small = new Chaîne (large.substring (...)) –

1

Je pense que vous devriez profiler votre application, avec et sans internage. Vous verrez alors exactement quel est l'effet.

Je ne crois pas qu'il existe un moyen de voir la taille du pool de constante de chaîne.

3

S'il s'agit d'un flux d'objets, ils ne vont pas dans le pool de constantes String sauf si vous appelez intern(), pour autant que je sache. La consommation de mémoire pour les chaînes internées ne provient pas du tas, mais de l'espace mémoire Perm Gen, donc si vous insérez beaucoup de chaînes, l'application plante avec OutOfMemory, même s'il reste beaucoup de Heap. Par conséquent, cela ne devrait pas poser de problème à moins que vous n'internalisiez toutes ces chaînes. Si cela devient un problème, il serait possible d'avoir votre propre implémentation Map pour stocker ces chaînes, donc vous n'utilisez pas le mécanisme interne.

J'ai vérifié l'implémentation de la méthode intern() et il est natif, il ne semble donc pas facile de mesurer la consommation de mémoire ou de voir le contenu du pool.

Vous pouvez utiliser ce drapeau pour augmenter le PermSize si vous manquez de mémoire:

-XX:MaxPermSize=64m 
0

Ne sachant pas exactement quel est le programme, je peux seulement vous suggérer d'essayer d'utiliser les chaînes comme un flux, et de ne pas stocker la chaîne dans son ensemble. Peut-être avez-vous besoin de faire plus d'abstractions pour votre application et d'inventer une représentation intermédiaire plus efficace sur le plan de la mémoire?

0

En Java 1.7 substring() - méthode n'utilise pas plus le même char [] il est plutôt copier la chaîne de sous dans le nouveau tableau-à-dire

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

qui tout au constructeur de chaîne si beginIndex est pas zero ou endIndex n'est pas égal à la longueur du tableau 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); 
    } 
Questions connexes