Как протестировать WeakReference в потоке?
Я хочу разобраться как работает WeakReference на простом примере. Есть подозрения что в моей программе WeakReference в отдельном потоке становится strong ссылкой.
Попытался сделать следующим образом:
public class TestWeak {
private static Object object;
private static WeakReference<Object> wr;
private static Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Object object4 = object;
System.out.println("Object4: " + object4);
Object object5 = wr.get();
System.out.println("Object5: " + object5);
System.out.println("Setting object to null");
object = null;
System.out.println("Running Garbage Collection...");
Runtime.getRuntime().gc(); // run GC to collect the object
Thread.sleep( 1000 );
System.out.println("Setting object4 to null");
object4 = null;
System.out.println("Running Garbage Collection...");
Runtime.getRuntime().gc(); // run GC to collect the object
Thread.sleep( 1000 );
System.out.println("Setting object5 to null");
object5 = null;
System.out.println("Running Garbage Collection...");
Runtime.getRuntime().gc(); // run GC to collect the object
}
catch (Exception e) {
e.printStackTrace();
}
}
};
public static void main(String[] args) throws InterruptedException {
object = new Object();
// Create a new weak reference that refers to the given object and is registered with this queue.
wr = new WeakReference<Object>(object); // , rq);
System.out.println("Object: " + object);
Object object2 = wr.get();
System.out.println("Object2: " + object2);
Object object3 = object2;
System.out.println("Object3: " + object3);
// start a new thread that will remove all references of object
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.schedule(runnable, 2, TimeUnit.SECONDS);
System.out.println("Wait ....");
boolean flag = true;
while (flag) {
if (wr.get() == null) {
System.out.println("Reference: " + wr);
System.out.println("Object is no longer referenced.");
flag = false;
}
}
service.shutdown();
}
}
Console:
Object: java.lang.Object@7852e922
Object2: java.lang.Object@7852e922
Object3: java.lang.Object@7852e922
Wait ....
Object4: java.lang.Object@7852e922
Object5: java.lang.Object@7852e922
Setting object to null
Running Garbage Collection...
Setting object4 to null
Running Garbage Collection...
Setting object5 to null
Running Garbage Collection...
Reference: java.lang.ref.WeakReference@3d4eac69
Object is no longer referenced.
Почему GC удаляет объект только после того как object5 (weak ссылка) устанавливается в null ?
UPDATE:
Если закомментировать эту строку:
// object5 = null;
Вы никогда не увидите в консоли:
Object is no longer referenced.
Наши заморские друзья говорят что GC работает как ему вздумается. https://stackoverflow.com/questions/29784793/java-weakreference-inside-thread
Но на мой взгляд приведенный пример никак не отражается на разной работе GC, а проблема заключается в неправильной работе/использовании WeakReference.
P.S. Так же пробовал параллельно переполнить память. Память переполнил, а в нужную строку в консоли так и не увидел.