Как грамотно очищать коллекции или объекты Java. Как не сожрать всю память
Я решил провести такой эксперимент.
public class Main {
public static final int mew = Integer.MAX_VALUE;
public static final String message = "A0yj8,fghfgh02fdgdrthrtfjfghfghfj";
public ArrayList<StringBuilder> list = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
final StringBuilder sb = new StringBuilder();
sb.append(message);
while (true){
main.clear();
Thread.sleep(1000);
main.addposition(sb.toString());
}
}
public void clear(){
for (StringBuilder sb : this.list){
sb.setLength(0);
}
list.clear();
list = new ArrayList<>(10);
}
public void addposition(String s ){
for (int i = 0 ; i < mew; i ++){
this.list.add(new StringBuilder().append(s+1));
}
}
}
Спустя пару секунд, монитор ресурсов становится красным а затраченная память улетает далеко за 1 гигабайт. Может я что-то делаю неправильно ?
Везде кричат что надо использовать StringBuilder, т.к String не изменяемый.
Ответы (1 шт):
Метод addposition в цикле 2 миллиарда раз добавляет в список объекты, каждый из которых содержит минимум 34 символа (+ накладные расходы на каждый объект StringBuilder и элемент в списке this.list). Т.е. при первом же вызове addposition самих только данных там минимум 34 * 2 * MAX_INT = 136 гигабайт и под все это идет выделение памяти.
Тут не важно, что делает clear вообще.
А вообще чтобы освободить память достаточно убедиться, что на объект нет ни одной обычной ссылки. В этом случае его соберет сборщик мусора. Не обязательно это произойдет сразу (т.к. JVM старается уменьшить накладные расходы на сборку мусора), но если программа запрашивает выделение памяти, а она занята мусором, то перед тем как случится OutOfMemoryError будет обязательно сделана полная сборка мусора.
Т.е. в этом случае (если абстрагироваться от того, что идет добавление 2 миллиардов объектов и предположить, что их меньше, так что все вместе они помещаются в доступную JVM память), list.clear достаточно, т.к. единственные ссылки на созданные объекты StringBuilder хранятся в списке this.list. Операция clear очистит список и все ссылки на эти объекты будут потеряны.