So I have this extremely memory-intensive Java application I'm building, which builds a tree of millions of nodes. Using the handy dandy Runtime methods for getting heap information, I built a nice little method that displays the current memory usage, as s开发者_Python百科hown below:
public void displayMemoryUsage() {
long maxMem = Runtime.getRuntime().maxMemory();
long freeMem = Runtime.getRuntime().freeMemory();
long heapMem = Runtime.getRuntime().totalMemory();
long usedMem = heapMem - freeMem;
System.out.println("Memory used: " + (int) (usedMem * 100 / maxMem) + "%");
}
So just to test it out, I had the tree expand its root node (into 2128 children), and then expanded each one of those children (for a total of approx. 4 million nodes in the tree). The memory displays 11% used. I then set the root of the tree to be one of the root's children, and in doing so remove all references to the root's other children. Theoretically, this should remove 2127/2128 of the original root's children. I ran Java's Runtime.getRuntime().gc() method for forced garbage collection, and told it to display the memory usage again. This time, I got 10%. In theory, should this new percentage not be more like 0.05%, or 1/2128th of the value before setting the new root?
Any thoughts why it's not picking up the garbage properly?
The System.gc
(and the equivalent Runtime.gc
) method is a suggestion to the garbage collector that garbage should be collected, so it not truly a way to "force garbage collection":
From the Java API Specification for the System.gc
method:
Runs the garbage collector.
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse.* When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
(Emphasis added.)
Furthermore, on a little bit of a technicality, even if the garbage collection did take place, keep in mind that there are other objects that are present on the Java virtual machine aside from your program, so there's going to be some memory overhead from that as well.
One way to actually get a rough idea of how much memory is being occupied by your tree is to check the memory usage before and after creating your tree -- but note that even then, there may be some garbage collection taking place while your tree is being built, so even that isn't going to be a perfect metric.
Probably the best option here is to employ a profiler (such as the jvisualvm
which comes with the JDK) to actually take a look at how much of the heap is being used by what.
You should try to profile your application instead!
- Are you sure there are no references to the deleted nodes anywhere?
- Are you sure you waited long enough after gc() i.e. did you suggest it multiple times?
精彩评论