-1

In the following code, will the emp object be garbage collected?

import java.util.HashMap;   
public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new 
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

It seems like it should be, but not according to this post:

What's the difference between SoftReference and WeakReference in Java?

Holger
  • 285,553
  • 42
  • 434
  • 765
Jack BeNimble
  • 35,733
  • 41
  • 130
  • 213
  • 2
    It would be really frightening if a `HashMap` would loose its contents for no reason. It’s not clear how the linked post should relate to your question at all. There are neither soft nor weak references in your code. – Holger Dec 13 '17 at 13:33
  • It's not a question about soft nor weak. The question is, if a HashMap has a strong reference to an object that is nulled, is the memory allocated to that object garbage collected? The author of the code I posted says no - " In the above situation, the object is not garbage collected." Seems like it should be. – Jack BeNimble Dec 13 '17 at 14:03
  • The post you have linked, does not contain the code of your question nor does it make any statement about it. It just describes the difference between soft and weak references. I fixed your link to point to the post actually containing the code and statement. – Holger Dec 13 '17 at 15:08
  • *"It seems like it should be"* ... I don't understand why you think it should. Is there any part in the JLS suggesting that or any sane reason why it should? – Tom Dec 13 '17 at 15:09
  • Ah, thanks. Yes, that's the code I was referring to. Do you agree with the author that the code isn't garbage-collected? It seems to me that it should be because it's been set to null, and therefore there's no point in preserving the memory it has allocated to it. But if it doesn't gc it, that's a sort of memory leak you would need to account for. – Jack BeNimble Dec 13 '17 at 15:14
  • Ok, got it. The hashmap still references it, so I can't be gc'd. – Jack BeNimble Dec 13 '17 at 15:23
  • 2
    I guess, the "nulling of an object" is the cause of your confusion. You can only "null" a reference, not an object. In `Object a = new Object(); Object b = a; a = null;` there's a single object reference temporarily twice and finally once. Any Collection has references to its members. All references you normally see are strong, these soft, weak and phantom references are used used very rarely (forget them for now). So no collection member can be GC'ed as long as it's still a member (forget `WeakHashMap` for now). – maaartinus Dec 13 '17 at 22:18

1 Answers1

2

Whether you set emp to null or not, is irrelevant. The application logic remains the same; you are putting an entry to the map, never remove it, thus the only valid answer to aMap.size() is 1 (one).

Even if your assumption, that you can never access the mapping, was right (it isn’t, you can retrieve the Employee instance via aMap.keySet().iterator().next(), to name just one example), e.g. if you create a class encapsulating another object that it never hands out, it didn’t allow to change the outcome of calculations based on the encapsulation, like the size reported by the HashMap.

A simple view on this issue, is, that you are holding a reference to HashMap, which in turn holds a reference to the Employee instance.

But actually, these objects can be garbage collected, as long as the JVM ensures the correctness of the program, e.g. ensures that the last print statement produces the output Size of Map1, which is technically possible without keeping the entire memory of the HashMap and its referenced objects. It would only have to keep the value of the int size field, or just remember the predictable string result.

But while this is allowed by the specification, it isn’t guaranteed. Garbage collection is a best-effort process. Collection of such apparently referenced objects only happens for optimized code and the JVM normally doesn’t optimize the code of an application consisting of a single main method that terminates within a few milliseconds.

The bottom line is, regardless of whether the JVM reclaims the memory behind the scenes, garbage collection will never cause a HashMap to spuriously change its size.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Let me rephrase the question - if I null out all the objects contained in a HashMap, will the overall memory usage be reduced? – Jack BeNimble Dec 13 '17 at 16:38
  • *No*. Either, the JVM is capable of detecting that the objects are actually unused, i.e. when optimizing the code, then it doesn’t matter whether you set the variables to `null`, or it doesn’t detect it; in that case, the fact that they are still referenced by the map matters. So in either case, setting the variables to `null` has no effect. – Holger Dec 13 '17 at 16:43
  • @Holger i absolutely always remember this : https://www.youtube.com/watch?v=M9o1LVfGp2A&t=29m&04s= when I think should I set something to null explicitly? never say never I guess :) – Eugene Dec 13 '17 at 21:36
  • @Eugene: there’s a difference between heap variables and the local variables of the question. Setting local variables to `null` rarely has any effect. In contrast, heap variables have an effect, besides the issues of the video, it’s mandatory to overwrite unused reference variables, e.g. within `ArrayList.remove`, it’s not sufficient to just change the size, it has to overwrite the last array entry with `null`, as otherwise, the garbage collector has no chance to understand that it is “semantically unreachable”. – Holger Dec 14 '17 at 08:51