Код, который вы опубликовали, не пропустит память.Однако цикл while (true)
никогда не прекратится, потому что s
никогда не будет null
в момент, когда вы его тестируете.
Позволяет немного изменить его, чтобы он работал "
public static void read(BufferedReader br) throws Exception {
long length = 0;
String s = "";
while (true) {
String ss = br.readLine();
if (ss == null) {
break;
}
s += ss;
length += ss.length();
}
System.out.println("Read: " + (length/1024/1024) + " MB");
}
Этот код также не пропускает память, поскольку все строки, созданные в методе, будут кандидатами на сборку мусора при возврате метода (если не раньше).
Каждый раз, когда мы выполняем s += ss;
создается новая строка, состоящая из всех символов, находящихся в настоящее время в s
, и символов в ss
.Предполагая, что имеется N строк, содержащих в среднем L символов, оператор s += ss;
будет вызван N раз, создаст N строк и скопирует в среднем (N * L)^2 / 2
символов.
Тем не менее, является хорошей причиной для создания StringBuilder
, то есть для уменьшения количества выделения строк и продолжения копирования символов.Давайте перепишем метод, чтобы использовать StringBuilder
;то есть замена StringBuffer
, который не синхронизирован.
public static void read(BufferedReader br) throws Exception {
long length = 0;
StringBuilder sb = new StringBuilder(sb);
while (true) {
String ss = br.readLine();
if (ss == null) {
break;
}
sb.append(ss);
length += ss.length();
}
System.out.println("Read: " + (length/1024/1024) + " MB");
}
Эта версия перераспределяет внутренний массив символов StringBuilder самое большее log2(N)
раз и копирует самое большее 2 * N * L
символов.
Резюме - использование StringBuilder - хорошая идея, но не из-за утечек памяти.Если у вас есть утечка памяти, ее нет в исходном примере кода или в фиксированной версии.