В слабой памяти, если я обновляю или изменяю ранее сохраненный ключевой объект, сборщик мусора удаляет пару ключ-значение - PullRequest
0 голосов
/ 23 октября 2019

Я сохранил объект как ключ в WeakHashMap. Теперь, если я изменю его значение, а затем вызову ГХ и напечатаю map, тогда ничего не останется.

public static void main(String[] args) throws InterruptedException{

    WeakHashMap map = new WeakHashMap();
    Integer obj = new Integer(200);
    map.put(obj, "sgdjsgd");
    obj=new Integer(20);
    System.gc();
    Thread.sleep(2000);
    System.out.println(map);
}
  • ожидаемый результат: {200,"sgdjsgd"}
  • фактический результат: {}

Ответы [ 5 ]

1 голос
/ 23 октября 2019

user207421 выразился очень точно: ваш код работает точно так, как задумано. Мне не совсем ясно, как вы пришли к тому, чтобы ожидать чего-то другого, но я хотел бы отметить:

  • Ваш код ничего не меняет внутри карты. Присвоение нового значения 20 obj только изменяет эту переменную. Ключом на карте по-прежнему является Integer, содержащий значение 200.
  • Назначение от 20 до obj гарантирует, что на карте нет других ссылок на ключ 200, поэтомусборщик мусора может удалить этот ключ с карты.

Если вы хотите изменить ключ на карте: никогда не делайте. Хеш-карта, включая WeakHashMap, хранит объекты по их хэш-коду. Изменение ключевого объекта наиболее вероятно изменяет хеш-код. Таким образом, карта не сможет снова найти ключ, даже если он там находится. Если вам нужна эта функциональность, вы должны сначала удалить ключ с карты, а затем вставить новый ключ:

    String value = map.remove(obj);
    obj = Integer.valueOf(20);
    map.put(obj, value);

С этим изменением вашего кода я получаю следующие выходные данные:

{20 = sgdjsgd}

1 голос
/ 23 октября 2019

WeakHashMap может вести себя так, как будто неизвестный поток молча удаляет записи.

WeakHashMap.Entry - это объект WeakReference, референтом которого является объект key, который вы передали map.put(). То есть, если key становится weakly reachable, сборщик мусора автоматически объявит его завершаемым.

В документе Java SE 8 написано , что :

Объект является слабо достижимым, если он не является ни сильно, ни мягко достижимым, но может быть достигнут, пройдя слабую ссылку. Когда слабые ссылки на слабодоступный объект очищаются, объект становится пригодным для завершения.

В этой строке вашего кода

    Integer obj = new Integer(200);
    map.put(obj, "sgdjsgd");

* obj являетсясильная ссылка на целочисленный объект, созданный new Integer(200), и затем он передается в map.put(), который создает WeakReference (при условии, что он называется w) для хранения этого целочисленного объекта.

Но после этой строки:

obj = new Integer(20);

obj указывает на другой целочисленный объект , который содержит 20 (w все еще указывает на целочисленный объект, который содержит 200). Но при изменении объекта, на который указывает obj, референт из w становится weakly reachable, потому что он может быть достигнут только при обходе слабой ссылки (а именно w).

Когда элемент управления возвращаетсяот вызова метода до System.gc() JVM сделала все возможное, чтобы утилизировать все отброшенные объекты. Таким образом, как сказано выше, сборщик мусора будет атомарно объявлять слабо достижимые объекты финализуемыми и, наконец, очищать их.

Таким образом, w очищается, запись на карте отбрасывается сборщиком мусора и какрезультат, ваша карта ничего не содержит.

0 голосов
/ 25 октября 2019
Integer obj = new Integer(200);

По умолчанию создается сильная ссылка на объект типа Integer obj ---- сильная ссылка ----> 200

map.put(obj, "sgdjsgd");

obj -- слабая ссылка -----> 200
Теперь целочисленный объект 200 имеет как сильную, так и слабую ссылку, поэтому он не подходит для GC

obj=new Integer(20);

obj ---- сильная ссылка----> 20

obj ----- X -----> 200 obj ---- слабая ссылка ---> 200

Здесь существующая сильная ссылка на 200 была потеряна. Таким образом, целочисленный объект 200 остается только со слабой ссылкой и будет с нетерпением собираться GC.

И из-за этого ключ также удаляется из weakHashMap

Проверьте эту ссылку для получения более подробной информации http://www.fis.unipr.it/lca/tutorial/java/refobjs/about/weak.html

0 голосов
/ 23 октября 2019

Я не уверен, что вы пытаетесь сделать, но то, что я вижу в вашем коде, это то, что вы назначаете новый объект для ссылки, которая ранее указывала на ключ в WeakHashMap, выполняя это, оригинальный ключ (Integer(200)) не имеет указателя, поэтому он бесполезен, потому что вы никогда не сможете достичь этого ключа, поэтому логично, что gc его удастся

0 голосов
/ 23 октября 2019

С помощью этого кода вы меняете указатель в памяти, которая хранится в obj:

obj=new Integer(20);

Перед этой строкой obj содержал указатель на ссылку new Integer(200);

Теперь вместо этого obj содержит ссылку на указатель на new Integer(20);, которая отличается от предыдущей в памяти.

Следовательно, поскольку WeakHashMap содержит слабую ссылку, когда сборщик мусора запускает еесобрать объект, на который ссылается карта, поэтому при печати карты он показывает {}, поскольку указатель, сохраненный в ключе карты, больше не обнаруживается.

...