Hors de la mémoire: en termes de laïc, cela signifie qu'il n'y a pas assez de mémoire. Par exemple, la création constante d'un grand objet dans une boucle infinie provoquera bientôt un débordement de mémoire.
Fuite de mémoire: fait référence à la libération de mémoire en temps opportun après avoir alloué la mémoire à un objet lorsque l'objet n'est plus utilisé, ce qui entraîne l'occupation de l'unité de mémoire et que la mémoire disponible réelle est réduite, tout comme une fuite de mémoire.
Fuite de mémoire causée par la méthode de la sous-chaîne
substring (int BeginIndex, int endndex) est une méthode de la classe de chaîne, mais cette méthode est implémentée complètement différemment dans JDK6 et JDK7 (bien qu'elles obtiennent toutes les deux le même effet). Comprendre leurs détails de mise en œuvre peut vous aider à mieux les utiliser, car une mauvaise utilisation de la sous-chaîne dans JDK1.6 peut entraîner de graves problèmes de fuite de mémoire.
1. Le rôle de la sous-chaîne
La méthode substring (int BeginIndex, int endIndex) renvoie une sous-chaîne, à partir du début de la chaîne parent et se terminant sur Endindex-1. L'indice de la chaîne parent démarre à 0, et la substring contient BeginIndex et non Endindex
String x = "ABCDEF"; x = str.substring (1,3); System.out.println (x);
La sortie du programme ci-dessus est "BC"
2. Principe de mise en œuvre
La classe String est immuable. Lorsque X est réaffecté dans la deuxième phrase ci-dessus, il pointera vers un nouvel objet String. Cependant, il n'y a pas de description précise ou représente la situation réelle qui se produit dans le tas. Ce qui se passe vraiment lorsque la sous-chaîne est appelée est la différence entre les deux.
Implémentation de la substrating dans JDK6
L'objet String est stocké sous forme de tableau char. Il y a 3 champs dans la classe String: CHAR [] Valeur, Int Offset et int count, qui sont respectivement utilisés pour stocker le tableau de caractères réel, la position de départ du tableau et le nombre de caractères de la chaîne. Ces 3 variables peuvent déterminer une chaîne. Lorsque la méthode de la sous-chaîne est appelée, elle créera une nouvelle chaîne, mais la valeur de tableau de char ci-dessus utilisera toujours la valeur du tableau parent d'origine. La seule différence entre le tableau parent et le tableau enfant est que les valeurs de nombre et de décalage sont différentes.
Jetez un œil au code source de l'implémentation de la sous-chaîne dans JDK6:
public String substring (int BeginIndex, int endIndex) {if (beginIndex <0) {throw new StringIndexoutofBoundSexception (beginIndex); } if (endIndex> count) {throw new StringIndexoutofBoundSexception (endIndex); } if (beginIndex> endIndex) {throw new StringIndexoutofBoundSexception (endIndex - BeginIndex); } return ((beginIndex == 0) && (endIndex == count))? Ceci: new String (Offset + BeginIndex, endIndex - BeginIndex, valeur); // il est utilisé pour utiliser la même valeur de tableau de char de char que la chaîne parent} String (int offset, int count, char char []) {this.value = value; this.offset = offset; this.count = count; }String str = "ABCDEFGHIJKLMNOPQRST"; String Sub = Str.SubString (1, 3); str = null;
Ce programme simple a deux variables de chaîne STR et Sub. La sous-chaîne est obtenue par la chaîne parent STR. Si le programme ci-dessus est exécuté dans JDK1.6, nous savons que l'attribution de l'espace mémoire du tableau est effectuée sur le tas, alors la valeur interne du tableau char de Sub et STR est la même, c'est-à-dire le tableau char ci-dessus composé de caractères a ~ caractère t. La seule différence entre STR et Sub est la différence entre BeginIndex et le nombre de longueurs de caractère dans le tableau. Dans la troisième phrase, nous rendons la référence STR vide, qui est destinée à libérer l'espace occupé par STR, mais à l'heure actuelle, GC ne peut pas recycler ce grand réseau de char car il est toujours référencé à l'intérieur de la sous-chaîne, bien que Sub n'intercepte qu'une petite partie de ce grand tableau. Lorsque STR est une très grande chaîne, ce déchet est très évident et peut même entraîner des problèmes de performance. Vous pouvez résoudre ce problème par:
Il utilise une technologie d'épissage de chaîne, qui créera une nouvelle chaîne. Cette nouvelle chaîne utilisera un nouveau tableau de char interne pour stocker les caractères dont il a réellement besoin, afin que le tableau char de la matrice parent ne soit pas référencé par d'autres sources. Soit str = null, et tout l'espace occupé par STR sera recyclé dans la prochaine fois que GC sera recyclé. Mais écrire comme celui-ci n'est évidemment pas beau, donc dans JDK7, la sous-chaîne est réimplémentée.
Implémentation de la substration dans JDK7
Amélioration de la mise en œuvre de la sous-chaîne dans JDK7, ce qui crée en fait un nouveau réseau de char dans le tas pour les sous-chaînes interceptées pour contenir des caractères pour les sous-chaînes.
Vérifiez le code source d'implémentation de la méthode de sous-chaîne de la classe de chaîne dans JDK7:
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) {lancez new StringIndexoutofBoundSexception (sublen); } return ((beginIndex == 0) && (endIndex == value.length))? ceci: new String (valeur, beginIndex, sublen); } public String (char Char [], int offset, int count) {if (offset <0) {throw new StringIndexoutofBoundSexception (offset); } if (count <0) {throw new StringIndexoutofBoundSexception (count); } // Remarque: le décalage ou le nombre peut être proche -1 >>> 1. if (offset> value.length - count) {throw new StringIndexoutofBoundSexception (offset + count); } this.value = arrays.copyofrange (valeur, décalage, décalage + count); }La méthode CopyOfRange de la classe des tableaux:
public static char [] copyofRange (char [] original, int from, int to) {int newLength = to - from; if (newLength <0) lance un nouveau IllégalArgumentException (de + ">" + à); char [] copy = new char [newLength]; // Il s'agit de créer un nouveau système de tableau char.ArrayCopy (original, de, copy, 0, math.min (original.length - from, newLength)); retourner la copie; }On peut constater qu'un nouveau tableau char est créé pour que la sous-chaîne stockait les caractères de la sous-chaîne. De cette façon, il n'y a pas de connexion nécessaire entre la chaîne enfant et la chaîne parent. Lorsque la référence de la chaîne parent n'est pas valide, GC recycle en temps opportun l'espace mémoire occupé par la chaîne parent.
Résumer
Ce qui précède est l'explication complète de la fuite de mémoire causée par la méthode de la sous-chaîne en Java. J'espère que ce sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!