Из памяти: с точки зрения непрофессионала это означает, что память не хватает. Например, постоянное создание большого объекта в бесконечном цикле скоро вызовет переполнение памяти.
Утечка памяти: относится к своевременному освобождению памяти после распределения памяти объекту, когда объект больше не используется, что приводит к тому, что блок памяти занят, и фактическая доступная память уменьшается, как утечка памяти.
Утечка памяти, вызванная методом подстроки
Substring (int beginindex, int endndex) является методом класса строки, но этот метод реализуется совершенно по -разному в JDK6 и JDK7 (хотя они оба достигают одного и того же эффекта). Понимание деталей их реализации может помочь вам лучше использовать их, потому что неправильное использование подстроки в JDK1.6 может привести к серьезным проблемам утечки памяти.
1. Роль подстроения
Метод подстроения (int beginindex, int endindex) возвращает подстроение, начиная с начала родительской строки и заканчивая в Endindex-1. Индекс родительской строки начинается с 0, а подстроение содержит BeginIndex, а не Endindex
String x = "abcdef"; x = str.substring (1,3); System.out.println (x);
Вывод вышеприведенной программы - «BC»
2. Принцип реализации
Класс строки неизменен. Когда X переназначен во втором предложении выше, он будет указывать на новый объект String. Однако не существует точного описания или представляет фактическую ситуацию, которая возникает в куче. То, что действительно происходит, когда называется подстроение, это разница между ними.
Реализация подстроки в JDK6
Строковой объект хранится как массив ЧАР. В классе String есть 3 поля: значение char [], int offset и int count, которые соответственно используются для хранения реального массива символов, начальной позиции массива и количества символов строки. Эти 3 переменные могут определить строку. Когда метод подстроения будет вызван, он создаст новую строку, но приведенное выше значение массива char все равно будет использовать значение исходного родительского массива. Единственная разница между массивом родителей и дочерней массивы заключается в том, что значения счета и смещения различны.
Посмотрите на исходный код реализации подстроки в JDK6:
public String substring (int beginindex, int endindex) {if (beginIndex <0) {бросить новый stringIndexoutOfBoundSexception (beginIndex); } if (endidex> count) {бросить новый stringIndexoutOfBoundSexception (endIndex); } if (beginIndex> endIndex) {бросить новый stringIndexoutOfBoundSexception (endIndex - beginIndex); } return ((beginindex == 0) && (endindex == count))? это: новая строка (Offset + BeginIndex, Endindex - BeginIndex, значение); // используется для использования того же значения массива char, что и родительская строка} String (int offset, int count, char value []) {this.value = value; this.offset = offset; this.count = count; }String str = "abcdefghijklmnopqrst"; string sub = str.substring (1, 3); str = null;
Эта простая программа имеет две строковые переменные Str и sub. Субной строки получается родительской строкой Str. Если вышеупомянутая программа запускается в JDK1.6, мы знаем, что распределение пространства памяти массива выполняется на куче, то значение внутреннего массива SUB и STR одинаковое, то есть приведенный выше массив ChAR, состоящий из символов A ~ символ t. Единственная разница между STR и SUB - это разница между BeginIndex и подсчетом длины символов в массиве. В третьем предложении мы делаем ссылку на STR пустым, что предназначено для освобождения пространства, занятого STR, но в настоящее время GC не может переработать этот большой массив, потому что на него все еще ссылаются внутри подгруппа, хотя Sub перехватывает только небольшую часть этого большого массива. Когда STR является очень большой струной, эти отходы очень очевидны и могут даже вызвать проблемы с производительностью. Вы можете решить эту проблему:
Он использует технологию сплайсинга строк, которая создаст новую строку. Эта новая строка будет использовать новый внутренний массив Char для хранения символов, в которых он фактически нуждается, так что на массив MARINAT MARPE не будет ссылаться другие источники. Пусть str = null, и все пространство, занятое STR, будет переработано в следующий раз, когда GC будет переработан. Но писать, как это, очевидно, не красиво, поэтому в JDK7 подстроение переосмысливается.
Реализация подстроки в JDK7
Улучшенная реализация подстроки в JDK7, которая фактически создает новый массив CHAR в куче для перехваченных подстроков для хранения символов для подстроков.
Проверьте исходный код реализации метода подстроения класса строки в JDK7:
public String substring (int beginindex, int endindex) {if (beginIndex <0) {бросить новый stringIndexoutOfBoundSexception (beginIndex); } if (endIndex> value.length) {бросить новый stringIndexoutofboundsexception (endidex); } int sublen = endindex - beginIndex; if (sooblen <0) {бросить новый stringIndexoutofboundsexception (sooblen); } return ((beginindex == 0) && (endindex == value.length))? это: новая строка (значение, beginindex, sooblen); } public String (char value [], int offset, int count) {if (offset <0) {throw new stringIndexoutOfBoundsexception (offset); } if (count <0) {бросить новый stringIndexoutofboundsexception (count); } // ПРИМЕЧАНИЕ: смещение или счет может быть близок к -1 >>> 1. if (offset> value.length - count) {бросить новый stringIndexoutofboundsexception (offset + count); } this.value = arrays.copyofrange (значение, смещение, смещение+count); }Метод CopyOfrange класса массивов:
public static char [] copyOfrange (char [] Original, int от, int to) {int newlength = to - from; if (newlength <0) бросить новый allosalargumentException (from + ">" + to); char [] copy = new char [newlength]; // это создать новую систему char массив. вернуть копию; }Можно обнаружить, что для подстроения создается новый массив CHAR для хранения персонажей в подстроении. Таким образом, нет необходимой связи между детской строкой и родительской строкой. Когда ссылка на родительскую строку недействительна, GC своевременно перерабатывает пространство памяти, занятое родительской строкой.
Суммировать
Выше приведено полное объяснение утечки памяти, вызванной методом подстроки в Java. Я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!