Статьи

Интересная утечка

Используете ли вы приложение WeakHashMap со строковым ключом? Пауза. Вот что вам нужно знать, работая с таким WeakHashMap. Эта статья взята из нескольких постов, сделанных в моем блоге .

Часть-1

Это снова одно из тех интересных наблюдений, с которыми я столкнулся во время некоторых оптимизаций памяти CXF . По совпадению здесь также его WeakHashMap .
Рассмотрим фрагмент кода ниже.

public class TestWeakHashMap
{
private String str1 = new String("newString1");
private String str2 = "literalString2";
private String str3 = "literalString3";
private String str4 = new String("newString4");
private Map map = new WeakHashMap();

private void testGC() throws IOException
{
map.put(str1, new Object());
map.put(str2, new Object());
map.put(str3, new Object());
map.put(str4, new Object());

/**
* Discard the strong reference to all the keys
*/
str1 = null;
str2 = null;
str3 = null;
str4 = null;

while (true) {
System.gc();
/**
* Verify Full GC with the -verbose:gc option
* We expect the map to be emptied as the strong references to
* all the keys are discarded.
*/
System.out.println("map.size(); = " + map.size() + " " + map);
}
}
}

Какого мы ожидаем размера карты после полного GC? Я изначально думал, что он должен быть пустым. Но оказалось, что это 2.

Посмотрите, как инициализируются четыре строки. Два из них определены с помощью оператора « new» , тогда как два других определены как литералы. Строки, определенные с помощью оператора new ‘, будут размещены в куче Java, но строки, определенные как литералы, будут находиться в пуле литералов.
Строки, размещенные в буквальном пуле (пространство Perm), никогда не будут собираться мусором.
Это будет означать, что String ‘str2’ и ‘str3’ всегда будут иметь жесткие ссылки, и соответствующая запись никогда не будет удалена из WeakHashMap.

Поэтому в следующий раз вы создадитеновая строка () вставьте его в качестве ключа в WeakHashMap, а затем в intern () в String, будьте осторожны — на ваш ключ всегда будут ссылаться. [Вызов метода intern () для String добавит вашу String в пул литералов, если какая-либо другая String, равная этой String, не существует в пуле]

Часть 2

Это снова продолжение моего предыдущего поста — Интересная утечка .
Я был довольно удивлен после прочтения последующего поста Маркуса. Интересная утечка при использовании WeakHashMaps.
Что меня больше всего удивило, так это если бы ты положил

 («abc» + «def»). intern ();

как ключ в WeakHashMap, он не получает GC’d, тогда как

(новая строка («abc») + «def»). intern ()

поскольку ключ приводит к тому, что вход собирает мусор
Ха!
Перепробовал все комбинации. Нет ясности. В крайнем случае — Pinged Rajiv .
И так пошел разговор —

Я: Если вы поставите («abc» + «def»). Intern (); как ключ, он не получает GC’d , но если вы поставите (новый String ( «ABC») + «DEF») стажер (). он получает GC’d
Раджив: Decompile и посмотреть , если «а» + «DEF» в настоящее время преобразован в «abcdef» с помощью javac
Я: Да, это так. Так?
[Это может быть ключом. Я все еще думаю .. отметьте отметку отметьте ]

Раджив: Проверьте, если «abcdef» == (новая строка («abc») + «def»).intern ()
Я: Это … напечатано хэш-коды личности.
Раджив: В классе у вас есть и «abcdef», и (new String («abc») + «def»). Intern () и still
(new String («abc») + «def»). Intern () получает gc «эд?
Я: Боже! Тогда это не получит gc’d.
[Теперь Раджив взломает это — ]

Раджив: «Я думаю, что стажер — слабая карта, и у постоянного пула есть сильный реф ». Я: о! Я: В этом случае (новая строка («abc»)) .intern () ; должен получить GC в порядке? Но мы видели, что это не так. Maya происходит только тогда, когда someString равен ‘+’ d (new String («abc»)), а затем результирующая String интернируется. Мне:Просто (новая строка («abc»)). Intern () не получает GC’d.



Раджив: Когда вы говорите (новая строка («abc»)). Intern () в константном пуле есть строка «abc».
Я: Да, «abc» в пуле констант будет тем литералом, который мы создали и передали в качестве аргумента конструктору String.
Rajiv: (new String («abc»)). Intern () возвращает эту строку. Так что не получишь
меня. О, да. Понял!
Я: Таким образом, только когда вы делаете «+», вы получаете строку, которой нет в постоянном пуле, и, следовательно, она получает GC’d …
Раджив: да, верно.

Раньше я думал, что пул интернов и пул констант будут одинаковыми. Но предсказание Раджива о том, что стажер — слабая карта и постоянный пул с сильным реф, выглядит довольно убедительно.
Оо ля .. Это разгадало нашу тайну.

Первоначально опубликовано на: http://oughtts.bharathganesh.com