tags:

views:

439

answers:

5

I've create a trie tree with an array of children. When deleting a word, I set the children null, which I would assume deletes the node(delete is a relative term). I know that null doesn't delete the child, just sets it to null, which when using a large amount of words it causes to overflow the heap.

Running a top on linux, I can see my memory usage spike to 1gb pretty quickly, but if I force garbage collection after the delete (Runtime.gc()) the memory usage goes to 50mb and never above that. From what I'm told, java by default runs garbage collection before a heap overflow happens, but I can't see to make that happen.

+3  A: 

Are you are referring to the memory not being freed to the OS - i.e. top and similar programs show that the Java process takes 1GB of memory? Even though Java's garbage collector frees the memory from its heap, it can still keep hold of the memory so that future allocations don't need to request for more memory from the OS.

To see how much heap space is actually used by the Java objects, use VisualVM or a similar Java-specific tool. If your machine has lots of memory, then the JVM will use it (IIRC, especially the Server VM is tuned to reserve more memory), but you can always limit it with the -Xmx and other JVM options.

Esko Luontola
[Full GC 815615K->815615K(932096K), 1.6976420 secs][Full GC 815615K->29792K(566272K), 0.2920610 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOfRange(Arrays.java:3209) at java.lang.String.<init>(String.java:216)Is the exact error without explicitly stating garbage collection.I don't really want to increase the limit, I'd like to actually address the problem. I guess the problem is how do you delete arrays that aren't needed any more?
Nicholas
If you get such an error, then maybe you have a reference leak somewhere. Try using a memory profiler to find out whether the program is keeping hold of references to unused objects, so that the GC can not free them.
Esko Luontola
A: 

Memory allocated to a process (i.e. the JVM) is not necessarily given back to the OS in Unix. So even though the Java Virtual Machine may have fully garbage collected the heap, the process size may stay the same.

Ordinarily, this may not have much impact as the unused heap will be paged out and not paged back in again. Look at the difference between the Virtual Size (VSZ) and the Resident Set Size (RSS) in the output of ps -u the difference is how many pages are swapped out.

msw
A: 

An object will only be deleted after it can no longer be reached by links from any accessible object. Is it possible that you still have references to the objects concerned?

By the way, Runtime.gc() is sometimes only a hint that garbage collection should run.

crazyscot
So the grandchildren aren't deleted? When I do my delete, I simply set it's child node to null, but not the children's children, but those children weren't ever initialized, only create(Node[] children = new Node[26]).
Nicholas
+1  A: 

OK, you are getting a java.lang.OutOfMemoryError: Java heap space.
Most probably, Runtime.gc() won't help, because if it would, the JVM had already did a gc.

It's probably a memory leak. If I were you, I will review my code carefully and see if some reference is still hold by something.

So the grandchildren aren't deleted? When I do my delete, I simply set it's child node to null, but not the children's children, but those children weren't ever initialized, only create(Node[] children = new Node[26]

If you do children=null , yes, the entire array should be gc'd. Provided that you didn't gave that reference to something.

But who knows what the culprit is. It may not even these "children" Nodes. You might want to use visualVm and find out what object is accumulating. You can use more sophisticated tools like JProfiler and examine the references etc., but if you are simply building a trie, I guess it's simpler to walk-through your code and spot the leak.

Enno Shioji
+2  A: 

(this too long for a comment)

Contrarily to popular belief you CAN really force a GC in Java but this is not done using System.gc(). The way to really force a GC is to use JVMTI's ForceGarbageCollection() call. Don't ask me more, I asked a question here and nobody found it interesting (no upvotes) and nobody could answer it, yet JVMTI's ForceGarbageCollection() is how a lot of Java programs like IntelliJ, NetBeans, VisualVM, Eclipse etc. do really force a GC:

http://stackoverflow.com/questions/2178296/java-how-do-you-really-force-a-gc-using-jvmtis-forcegargabecollection

Now... You probably do not want to do that and you probably do not want to hint the GC using the "no guarantee" System.gc() call.

At how many words do you start having problems? There are very compact data structure when you need to work with insane number of words. Are you sure you're using the correct data structure and are you sure you're not having leaks?

Webinator
interestingly, one person insulted me for that question I asked, saying I was lazy... Even tough that same person has reached 20K rep answering much easier questions, asked for sure by people who did much less research than what I did on JVMTI. I flagged his comment insulting me as offensive and welcome anyone reading that question to do the same. Also if you think that knowing how to really do a GC would be a great addition to GC, than please upvote my question.
Webinator