I disagree with the accepted answer. I believe your answer of five objects being eligible for garbage collection is actually correct, and the exercise you are working from is wrong (Although if anyone can explain how I'm mistaken, I'd greatly appreciate it).
Here are the objects that are referenced by your program:
Integer
#0 - The Integer
created by static Integer value = new Integer()
*
Currency
#1 - The Currency
created by Currency.getCurrency(50)
.
Integer
#1 - The Integer
returned by the autoboxing of 50
.
String
#1 - The String
created by String name = new String()
in Currency
#1's creation.
Currency
#2 - The Currency
created by Currency.getCurrency(100)
.
Integer
#2 - The Integer
returned by the autoboxing of 100
.
String
#2 - The String
created by String name = new String()
in Currency
#2's creation.
*this doesn't actually compile, but I'll assume it's replaced by valid code which doesn't otherwise affect the program.
So seven objects are required for your code to function. The object initially referenced by value
becomes eligible for garbage collection when value
is overwritten with 50
. The first and second Currency
s are eligible at the end of m
when their only references go out of scope. The first and second String
s are eligible at the end of m
, when their only referencing objects, Currency
s 1 and 2, go out of scope. The autoboxed Integer
from 100
is clearly still referenced at the end by the static reference value
, and so is not eligible for garbage collection. That's 5 objects eligible, 1 ineligible, and one not yet discussed.
The last object is the Integer
returned by the autoboxing of 50
. Your code obviously no longer references it, since value
is set to reference 100
instead. This would seem to indicate that it's eligible for garbage collection, but I disagree. The Integer
class is know to cache values at least in the range -128
to 127
in order to conform to JLS 5.1.7. So when m
exits, the cache will still contain a reference to the boxed Integer
from 50
, causing it to be ineligible for garbage collection.
I attempted to test this behavior with this program:
public class Test{
public static final WeakReference<Integer> inCache = new WeakReference<>(50);
public static final WeakReference<Integer> outOfCache = new WeakReference<>(10000);
public static void main(String[] args){
System.gc();
System.out.println(inCache.get());
System.out.println(outOfCache.get());
}
}
Which outputs
50
null
showing that, at least in this case, the uncached Integer
was garbage collected and the cached one was not. This suggests that even with no explicit reference to 50
, it is still ineligible for garbage collection because of the stored reference in the cache.
I'll admit that this doesn't prove anything since, for one, System.gc()
does not guarantee that it will collect all (or any) available memory. However, I think this should show that the problem isn't as straightforward as one might assume and, on the most common JDK/JVMs, it's plausible that the sixth value is not eligible for garbage collection.
TL;DR - I don't think the Integer
returned by boxing 50
is eligible for garbage collection, because it is still referenced by the cache maintained by the Integer
class.