Reputation: 1
Edit: There is no memory leak, just a noobs misunderstanding of what the Netbeans Profiler is telling me. Live Profiling Results -> Allocated Objects refers to the TOTAL allocated over the lifetime of the program, not the total currently in memory. For that, get a heap dump. Sorry for the confusion, but maybe someone else will find this and it will clear that up for them.
Im using the NetBeans 7.0.1 profiler to troubleshoot memory growth in my application, and am seeing two major issues. Ive successfully created test applications and see the same results in the profiler, included below. I wasnt able to find a reference to these anywhere else.
Case 1: Looping through the entryset of a HashMap causes the object java.util.HashMap&EntryIterator to grow. Is there anything to do here except figure out a solution with a different container? Looping through the collection every time in the while loop is necessary to our application.
public static void main(String[] args) throws InterruptedException {
boolean run = true;
HashMap<Integer, Integer> map = new HashMap<Integer, Integer> ();
map.put(1, 2);map.put(3, 4);map.put(5, 6);map.put(7, 8);
while(true){
for (Entry<Integer, Integer> entry : map.entrySet()) {
Integer i = entry.getValue();
}
//app specific code here
Thread.sleep(50);
}
}
Case 2: Creating empty ArrayLists in a loop causes a growth of java.lang.Object[]. I would expect the ArrayLists to be eligible for GC at the end of the while loop. Is my assumption wrong? Or is something else at play here?
public static void main(String[] args) throws InterruptedException {
boolean run = true;
while(run){
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
// app specific code here
Thread.sleep(50);
}
}
Upvotes: 0
Views: 5854
Reputation: 161
I have run the above code and I can confirm that this is not a memory leak. Because when I run the GC, all the ArrayList objects are reclaimed.Assumption is that it commented app code is not adding up to the issue
Regards, Lalitha
Upvotes: 0
Reputation: 61705
A lot of what you're saying depends upon the lines like:
// app specific code here
What you're doing here can affect the garbage collection a lot. For the code you've posted, this will cause memory leaks. For instance, each time through this loop:
public static void main(String[] args) throws InterruptedException {
boolean run = true;
while(run){
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
// app specific code here
Thread.sleep(50);
}
}
the objects allocated become available for garbage collection. The memory may continue to grow until it reaches its allocated limit, but after that the objects will be garbage collected.
Run your code outside netbeans, and run jvisualvm on it. See what is really happening.
Upvotes: 0
Reputation: 340733
Although I can't find anything disturbing, I just tried both of your code snippets. I removed sleep
s to speed up testing. Garbage collector works like crazy several times per second and essentially cleans the whole young generation (try with -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
):
[GC [PSYoungGen: 104272K->0K(99712K)] 105235K->963K(131968K), 0.0008090 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
The code run for few minutes with very high CPU utilization, but memory usage was stable. There is definitely no memory leak in both code samples.
What you are probably observing is incremental growth of heap (young generation in JVM is basically a stack, allocating new objects on top of each other and not bothering about garbage). The garbage collection runs when the stack is exhausted.
Upvotes: 0
Reputation: 20323
In your both examples methods aint finishing hence even if GC runs it cannot claim these objects.
Even if your objects were initialized outside the loop then also on some compilers the bytecode would have been same as they were created inside loop, there is not much of a difference.
Moreover you cannot guarantee if GC will ever run and your objects will be reclaimed.
EDIT:
Similar post on SO
Upvotes: 0
Reputation: 10226
Your ArrayLists in your second example would be eligible for GC as long as there is no other code that references them. In addition, you have no control over how and when a garbage collection is executed. Do you know what garbage collector you are using? Do you run your program with any specific vm flags? Do you experience strange behavior after you call System.gc in order to force a garbage collection? Does your app specific code reference your array lists?
Upvotes: 0
Reputation: 6182
I don't think that either code sample is leaking memory. You must be sure to distinguish between "the heap grows until the garbage collector runs" and "the heap grows forever". If you remove the Thread.sleep calls and run either app forever it should not crash and the JVM's heap usage should rise and fall as the garbage collector runs. You can try running "System.gc()" during each loop and seeing if your profiler still shows a leak.
Upvotes: 2