WeakHashMap постоянно растет, или он очищает мусорные ключи? - PullRequest
0 голосов
/ 13 октября 2018

Я пытаюсь использовать WeakHashMap в качестве одновременной Set слабых ссылок.

    this.subscribers =
            Collections.synchronizedSet(
                    Collections.newSetFromMap(
                            new WeakHashMap <>()
                    )
            );

Когда элемент попадает в сборщик мусора, мой набор продолжает сообщать о нем как о части сбора.Так что, похоже, карта постоянно растет.

Документация гласит:

Когда ключ отбрасывается, его запись эффективно удаляется с карты,…

Но, похоже, это не такбыть на практике.

Есть ли когда-нибудь точка, в которой WeakHashMap очищает детрит?

1 Ответ

0 голосов
/ 13 октября 2018

Да, ключи очищены после того, как мусор фактически собран

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

Вероятно, вы ошиблись в том, что ваши объекты отправляются на сборку мусора.Возможно, ваши объекты стали кандидатами для сборки мусора, но еще не были собраны.Попробуйте вызвать сборщик мусора и подождите, пока он не завершится.Но помните, что вызов System.gc() является всего лишь предложением для JVM и может игнорироваться в зависимости от вашей реализации JVM и текущего сценария времени выполнения.

Вот полный пример приложения.Обратите внимание, что Set сообщает об уменьшении size при вызове Set::remove или выходе объекта из области видимости.

package com.basilbourque.example;

import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;

public class WeakHashMapExercise {

    public static void main ( String[] args ) {
        WeakHashMapExercise app = new WeakHashMapExercise();
        app.doIt();
    }

    private void doIt ( ) {
        Set < UUID > set =
                Collections.synchronizedSet(
                        Collections.newSetFromMap(
                                new WeakHashMap <>()
                        )
                );

        UUID uuid1 = UUID.fromString( "a8ee1e34-cead-11e8-a8d5-f2801f1b9fd1" );
        UUID uuid2 = UUID.fromString( "39bda2b4-5885-4f56-a900-411a49beebac" );
        UUID uuid3 = UUID.fromString( "0b630385-0452-4b96-9238-20cdce37cf55" );
        UUID uuid4 = UUID.fromString( "98d2bacf-3f7f-4ea0-9c17-c91f6702322c" );

        System.out.println( "Size before adding: " + set.size() );

        set.add( uuid1 );
        set.add( uuid2 );
        set.add( uuid3 );
        set.add( uuid4 );

        System.out.println( "Size after adding 4 items: " + set.size() );  // Expect 4.

        set.remove( uuid3 );

        System.out.println( "Size after removing item # 3: " + set.size() );  // Expect 3.

        uuid2 = null;  // Release that UUID to garbage-collection.

        // That released object may still appear in our `Set` until garbage collection actually executes. 
        System.gc(); // Ask the JVM to run the garbage-collection. Only a suggestion, may be ignored.
        try {
            Thread.sleep( 1_000 );  // Wait a moment, just for the heck of it.
        } catch ( InterruptedException e ) {
            e.printStackTrace();
        }

        System.out.println( "Size after making garbage of item # 2: " + set.size() );  // Expect 2.

        for ( UUID uuid : set ) {
            System.out.println( uuid.toString() );
        }


    }
}

См. Этот код, запущенный на IdeOne.com .

Размер до добавления: 0

Размер после добавления 4 элементов: 4

Размер после удаления элемента # 3: 3

Размерпосле изготовления мусора элемента # 2: 2

В моем случае, с использованием Java 10.0.2 версия OpenJDK на основе Zulu JVM из Azul Systems , сборщик мусора, похоже, активируется по моей просьбе.Если я закомментирую задержку на секунду или вызов System.gc, то последним сообщенным размером останется 3, а не ожидаемый 2.

Вы можете даже увидеть это поведение, когда запуск этого кода в прямом эфире на IdeOne.com .Обратите внимание, что последний элемент ниже 3, но выше 2.

Размер перед добавлением: 0

Размер после добавления 4 элементов: 4

Размер после удаления предмета № 3: 3

Размер после изготовления предмета № 2: 3

...