Reputation: 4546
In Java, having a nested static class Human
, I'm wondering if after cleanup of the map
variable can make it available for garbage collected. At the moment just before doSomeCode()
I called System.gc()
and added Thread.sleep(60000)
to wait for garbage collector to pick up unreferenced map
contents, but no way - it seems map
lives in a program unless it is going to finish. My problem is that I need to free up memory because otherwise will get OutOfMemoryError
.
What do you think prevents map
property of Human
class from being recycled? Is it because the Human
class is static and thus all its members can not be garbage collected?
import java.util.List;
import java.util.ArrayList;
import com.carrotsearch.hppc.IntObjectMap;
import com.carrotsearch.hppc.IntObjectOpenHashMap;
public class TestNestedStaticClass {
public static class Human {
String name = null;
List<Human> children = null;
// some data about family members
IntObjectMap<int[]> map = null;
public Human(String name) { this.name = name; }
}
public static void main(String[] args) {
final List<Human> family = new ArrayList<Human>();
for (int i = 0; i < 1000; i++) {
// create and get the family member
family.add(new Human("givenName"));
Human h = family.get(i);
// create map and add some data
h.map = new IntObjectOpenHashMap<int[]>();
for (int j = 0; j < 100; j++) {
int[] array = new int[1500];
h.map.put(j, array);
}
}
// ...
// at some point we want to free the memory occupied by
// family.get(i).map for all i from 0 to 1000, so we do:
for (int i = 0; i < 1000; i++) {
// get the family member
Human h = family.get(i);
// explicitly remove references from the map
for (int j = 0; j < 100; j++) {
h.map.remove(j);
}
// cleanup
h.map.clear();
h.map = null;
}
// ...
doSomeCode();
}
}
Upvotes: 1
Views: 1512
Reputation: 2013
It looks like you are using all primitive data types. This might be a problem, this is just a theory, and I haven't tested it, but it might be worth a try.
Instead of using an array of int's ( int[] ), try using an ArrayList. This should create objects which can be garbage collected, primitive data types are created on the stack not on the heap of objects, therefore they aren't subject to garbage collection?
NOTE: I put a question mark, because I am not positive, someone can confirm or reject my theory.
THEORY REJECTED :( , LEAVING AROUND FOR OTHERS TO READ
Upvotes: 0
Reputation: 328598
From the point where you write: h.map = null;
, the map becomes eligible for GC (the removes and clear are technically not necessary).
The reason why you don't see it being GC'ed is possibly due to the fact that you run all that code within the same method, and the GC does not have to collect local variables until the method exits.
If you try to split it in several method it will help the GC (which will get rid of the local variables once the methods exit).
See also this post.
ps: I assumed that you don't have any references to the content of the map or the map itself anywhere else!
Upvotes: 3
Reputation: 18148
There is no need to sleep after System.gc()
- the gc method doesn't return until the garbage collector is finished.
An instance of a static inner class is treated the same as an instance of any other class for purposes of garbage collection. You are correctly freeing the map
elements of your Human classes (although it's overkill to call map.remove()
and map.clear()
and map = null
- only map = null
is needed)
Upvotes: 0
Reputation: 3334
The fact that the Human class is static means nothing - and even if the map
variable was static, setting it to null frees up the object content for garbage collection.
If you are running into OutOfMemoryErrors, and you are certain the map contents are the cause, then there must be lingering references to the data somewhere. For example, if I do this:
human.map.put(0, new int[10000]);
something.thing = map.get(0);
human.map.remove(0);
human.map = null;
Note that a reference to the int[10000]
still remains in memory, @something.thing
. Cleaning up the map is only part of the work needed to free up the array for garbage collection.
Upvotes: 2
Reputation: 85779
Note that inner static
classes are indeed top classes but just inside a class
, so the GC rules to collect their instances are the same rules that GC applies on a common class instance.
Upvotes: 0
Reputation: 182
1) Been a while since I programmed in Java but my guess is the static objects/variables live on in a special place during whole execution of the program.
2) Calling GC explicitly doesn't ensure the objects will be deleted. You simply call the GC and it decides itself (and you cannot really affect this behavior).
Upvotes: -3