I have the below method.Suppose i call A.m1()
10,000 times from class B
.
So all 10,000 MyObj
objects will be garbage collected as their scope is only within the m1()
method.
There is no memory leak?
class A { String m1() { MyObj obj = new Mybj(); } }
And i call it below
class B { void m2() { String s = classAObj.m1(); } }
Advertisement
Answer
The references created in the method are eventually garbage collected when they go out of scope. But it doesn’t necessary happen immediately.
Here is a demo that shows that the references are collected. But first some terms.
- hard reference – A normal reference to an object that will be around
until it is garbage collected. These are the typical instance values resulting
from object creation. - weak references – references that point to the same object as a hard reference.
When a hard reference is garbage collected, the associated weak references are also collected.
How this works.
- The method
m1
is calledn
times, each time creating a weak reference of an instance ofA
and returning it. - This is then added to a list.
- Once the hard references are garbage collected, the weak references that refer to the same objects will also be collected
- The weak reference will then return null when trying to retrieve its associated
object.
import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; public class GarbageCollection { public static void main(String[] args) { // get out of static context new GarbageCollection().start(); } public void start() { int n = 10_000; List<WeakReference<A>> weak = new ArrayList<>();
Create n
weak references of A
by calling m1
and returning the reference.
Then it add to the List
.
for (int i = 0; i < n; i++) { WeakReference<A> wk = m1(); weak.add(wk); }
Now iterate thru the List of weak references to see how many are null.
Zero is expected
since the garbage collector has not yet run. All of those A
allocations created in m1
are still lurking around in the heap.
int count = 0; for (WeakReference<A> wk : weak) { if (wk.get() == null) { count++; } } System.out.println(count); // probably zero
Now repeat the same process but explicitly invoke the garbage collector.
count = 0; System.gc(); for (WeakReference<A> wk : weak) { if (wk.get() == null) { count++; } }
At this point, count should be non-zero (or possibly n
for small values of n
) to
show some or all of the objects have been collected.
System.out.println(count); } public WeakReference<A> m1() { A a = new A(); return new WeakReference<>(a); } } class A { }