5

Here I have an example:

import java.lang.ref.WeakReference;

public class WeakRefTest {
    public static void main(String[] args) {
        Object obj = new Object();
        WeakReference<Object> weakRef = new WeakReference<Object>(obj);
        int i = 0;
        while (true) {
            if (weakRef.get() != null) {
                i++;
                System.out.println("The object is alive for " + i + " loops - " + weakRef);
            } else {
                System.out.println("The object has been collected.");
                break;
            }
        }
    }
}

When running this program, we'll get output with "The object has been collected." after a while, which means the object will be gc-ed.

However, there is still a strong reference named "obj" linked to the object, how can it be reclaimed? Because JVM found there is no strong reference usage later, so it's not strong reachable?

Smile
  • 3,832
  • 3
  • 25
  • 39
zhuj9
  • 83
  • 4
  • _However, there is still a strong reference named "obj" linked to the object_ what exactly do you mean? Who exactly is keeping `Object` from being collected? – Eugene Dec 11 '19 at 14:23
  • 1
    @Eugene Why the reopen? The answer by Stuart Marks explains that `obj` could be collected regardless because there's nothing in the program, after it's been used to initialize the `WeakReference`, that makes use of it. Even though there's a "strong reference" to it on the stack, it cannot be "accessed in any potential continuing computation from any live thread" and therefore can be collected. The duplicate doesn't address the `WeakReference` but that's irrelevant to the behavior of the program, which is the collection of the `Object`. – Sotirios Delimanolis Dec 11 '19 at 23:21
  • 2
    Duplicate of [Can java finalize an object when it is still in scope?](https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope) – TylerH Dec 12 '19 at 15:02

2 Answers2

3

Since your loop is running quite "hot" in terms of resource usage, the JVM will want to optimize it. Doing so might point the compiler to the fact that in fact the strong reference can't be reached after entering the loop and thus optimize it away.

This behaviour will likely change if you add something like System.out.println(obj) after your loop. You might need to tweak your loop condition so that the compiler can't see that the new statement is in fact unreachable code... (something like while (weakRef.get() != null))

Nicktar
  • 5,548
  • 1
  • 28
  • 43
  • I don't get it, so how exactly did you understand this part of the question: _However, there is still a strong reference named "obj" linked to the object, how can it be reclaimed?_ Is the OP meaning `obj` reference to `weakRef`? If so, this has nothing to do with JVM optimizations – Eugene Dec 11 '19 at 14:35
  • The variable 'obj' is storing a reference to the object that's stored in weakRef too. – Nicktar Dec 12 '19 at 07:49
-1

A WeakReference does not make the referent strongly reachable, that would defeat the entire purpose of WeakReferences. So for example this:

 public static void main(String[] args) {

    Object obj = new Object();
    WeakReference<Object> weakRef = new WeakReference<>(obj);

    while (weakRef.get() != null) {
        System.out.println("Object is still alive");
        System.gc();
    }

    System.out.println("Collected : " + weakRef.toString());
}

We will still see Collected (eventually, hopefully), followed by some hash coming from toString; demonstrating that even if weakRef is not reachable, the referent is already gone.

Also, this sentence:

Because JVM found there is no strong reference usage later, so it's not strong reachable?

Do not confuse reachability with the type of reference, even strongly reachable objects can become reachable; in the same that they can be collected. Strongly reachable objects are nothing more than plain reference in java, imagine if this would not GC-ed...

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • I don't think they made the claim that a `WeakReference` made an object [strongly] reachable. They're talking about `obj` which, in their snippet, is never assigned any other value. There is therefore a strong reference to the `Object` object and the classic school of thought suggests that strong references prevent GC. Your snippet assigns `null` to `obj` and therefore removes the strong reference to the `Object` object, so you're changing the context of the question. – Sotirios Delimanolis Dec 11 '19 at 23:38
  • As for your last paragraph, what they're describing (with some wrong terminology) is actually what's happening. **A _reachable_ object cannot be finalized and collected.** So even though there is a strong reference to the object through the `obj` variable, the corresponding object is no longer reachable by the program, and that's why it can be collected (like the old duplicate link explains). I believe that's what their confusion was about. – Sotirios Delimanolis Dec 11 '19 at 23:49
  • @SotiriosDelimanolis indeed a duplicate, took a while for me to acknowledge that. – Eugene Dec 13 '19 at 14:21
  • All good, but do you also want to address these comments so I can revote ^? – Sotirios Delimanolis Dec 13 '19 at 16:17
  • @SotiriosDelimanolis ah! the assigning of `obj = null` is not something I should have posted, that I agree with – Eugene Dec 13 '19 at 16:24