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 {
}