So I learned that in a singly linked list if you remove a node in the middle, the rest of the list will be garbage collected as well since there will be a ripple effect as each node behind it gets dereferenced.
My question is what about a tree where each node has references to it's children as well as a reference to a parent. If I remove a node in the middle(non-leaf node) would that cause a memory leak since it would reference it's children and they would reference it? So if I wanted to remove a subtree, I would have to remove all the nodes in it from the bottom up?
You should read about the concept of reachability. It is defined in the javadocs, in the description of the package java.lang.ref.
Once an object is not strongly reachable by any thread, it is eligible for garbage collection.
The objects that are strongly reachable by a thread T are:
objects referenced by local variables in the call stack of T,
objects referenced by static fields of any classes, and
objects (strongly) referenced by strongly reachable objects.
If you remove a node from the tree you describe (simply by removing the reference on a parent node to a child), and there are no remaining references to the portion of the tree under the node you removed, then those objects are not strongly reachable. Even if they form some kind of cycle, the JVM is smart enough to determine that those objects are not strongly reachable (that is, they reference each other, but none of them can be reached by any code). Therefore, they are eligible for garbage collection.
You could remove the start node and remove the reference to that node in its parent.
To remove a subtree you just have to remove the reference to it in its parent. So long as no other references are held to it or its children, it will be garbage collected.
Related
I've noticed that a lot of code online for the remove node or delete node function of a singly LinkedList merely set the previous node's next to the next of the node to be removed. But isn't that an incomplete deletion, because the deleted node is still pointing to it's next?
For example
A->B->C
If you delete B, you should make A point to C. But if you don't make B point to null, doesn't B still exist because it's pointing to C?
Like wise, for a doubly linkedList in java, if you were deleting a node wouldn't you need to make sure that the node is no longer pointing to anything for it to be truly deleted?
if you don't make B point to null, doesn't B still exist because it's pointing to C?
No. The reason is that as there is not any reference towards B, it will be garbaged collected. It doesn't matter if it (B) is still pointing to something.
Like wise, for a doubly linkedList in java, if you were deleting a
node wouldn't you need to make sure that the node is no longer
pointing to anything for it to be truly deleted?
The principle is the same. What changes is that you need to change two references: the previous node of the node being deleted (making it point to the next of the node being deleted) and the next of the node being deleted (making it point to the previous of the node being deleted).
When there are no references to the node being deleted, this will be garbaged collected.
In general, when there isn't a reference pointing to some object, this will be garbaged collected at some point.
Here is a very similar post that may be useful to you: Garbage collector in java - set an object null
I presume you are talking about Javas LinkedList<>. It's probably because the garbage collector will get it.
No.It will be garbage collected.Unreachable objects which are no longer referenced by any part of the program will be cleared by garbage collector in java.Garbage collector frees up the heap memory by destroying the unreachable objects.
Most tree delete operations in Java go about setting each child to NULL so each node is garbage collected. Shouldn't simply setting the root to NULL work ?
Well, any object that cannot be reached by any live thread will be eligible for garbage collection, even if this you have a huge graph of objects that still reference each other (like a tree) but aren't reachable by any thread.
That said, setting the child references to null would not do anything for eligibility since if there is no reference to the root but there are still references to a node at least that node cannot be gc'd.
Depending on how the tree is set up setting every node reference to null might allow a huge part of the tree be collected, even if a node is still held elsewhere (not necessarily in your code).
Example:
Consider a linked list (degenerated tree) like this:
your code -> root <-> node1 <-> node2 <-> node3 <- some other code
If you set the reference to root to null in your code, the list still cannot be collected since there's some other code referencing node3 which in turn references the other nodes up to root.
However, if you remove references between the nodes as well, root, node1 and node2 can be collected - while node3 cannot. (In this case it would be sufficient to remove the reference from your code to root and from node3 to node2, but general code doesn't know which other nodes might still be referenced, so removing all tree-internal references is the safe way to go.)
All,
If I were to write a function to delete a node (given headNode and data as input parameters) from a linkedList in Java. I would find the node that has "node.data=data", and delete it by pointing its previous node to its next node *^. My question is, do we have to point the "to be deleted" node to null? to free the memory? or the GC will take care of objects no more accessed in heap.
*^: say A->B->C->D , if B.data=data, then make A->C . is B->Null necessary?
please let me know if its not clear, I will edit it. Thanks.
If you want to delete Node B you just need for A to point to C. The garbage collector will take care of your B nodes as there won't be any references left to it.
The following explanation is quoted from http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
Generally an object becomes eligible for garbage collection in Java on following cases:
1) All references of that object explicitly set to null e.g. object = null
2) Object is created inside a block and reference goes out scope once control exit that block.
3) Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
4) If an object has only live references via WeakHashMap it will be eligible for garbage collection.
As everyone has said you don't need to set it to null. I just want to add that I had a similar question before which might not be obvious. If you have a doubly linked list, where each node references the previous and the next node, for example A-B-C-D and you remove C-D so that you're left with A-B. You also do not need to worry about C or D even though both of them still have a reference to them (from the other one). Apparently the GC is smart enough to take care of that case as well
No you don't have to set B to null. The Java garbage collector will free the memory for any object not reachable anymore.
Suppose I have a doubly linked list. I create it as such:
MyList list = new MyList();
Then I add some nodes, use it and afterwards decide to throw away the old list like this:
list = new MyList();
Since I just created a new list, the nodes inside the old memory area are still pointing to each other. Does that mean the region with the old nodes won't get garbage collected? Do I need to make each node point to null so they're GC'd?
No, you don't. The Java GC handles cyclic references just fine.
Conceptually, each time the GC runs, it looks at all the "live" root references in the system:
Local variables in every stack frame
"this" references in every instance method stack frame
Effectively, all static variables (In fact these are really referenced by Class objects, which are in turn referenced by ClassLoaders, but lets ignore that for the moment.)
With those "known live" objects, it examines the fields within them, adding to the list. It recurses down into those referenced objects, and so on, until it's found every live object in the system. It then garbage collects everything that it hasn't deemed to be live.
Your cyclically referenced nodes refer to each other, but no live object refers to them, so they're eligible for garbage collection.
Note that this is a grossly simplified summary of how a garbage collector conceptually works. In reality they're hugely complicated, with generations, compaction, concurrency issues and the like.
If you created your own double linked list, and you put in this double linked list Containers (that contain items from your list); only those containers are linked one to another.
So in your list you'll have an object A contained in A'. A' is linked to B' and B' is a container that hold B etc. And none of the object have to reference another.
In a normal case those containers won't be available from outside (only the content is interesting); so only your list will have references to your containers (remember that your content isn't aware of his container).
If you remove your last reference to your list (the list, not the container nor the content) the GC will try to collect your list content, witch is your containers and your contents.
Since your containers are not available outside the only reference they have is one each other and the main list. All of that is called an island of isolation. Concerning the content, if they still have references in your application, they will survive the GC, if not they won't.
So when you remove your list only A' and B' will be deleted because even if they still have references, those references are part of an island. If A and B have no more references they will be deleted too.
No -- Java (at least as normally implemented) doesn't use reference counting, it uses a real garbage collector. That means (in essence) when it runs out of memory, it looks at the pointers on the stack, in registers, and other places that are always accessible, and "chases" them to find everything that's accessible from them.
Pointers within other data structures like your doubly-linked list simply don't matter unless there's some outside pointer (that is accessible) that leads to them.
No, the GC will reclaim them anyways so you don't need to point them to null. Here's a good one paragraph description from this JavaWorld article:
Any garbage collection algorithm must
do two basic things. First, it must
detect garbage objects. Second, it
must reclaim the heap space used by
the garbage objects and make it
available to the program. Garbage
detection is ordinarily accomplished
by defining a set of roots and
determining reachability from the
roots. An object is reachable if there
is some path of references from the
roots by which the executing program
can access the object. The roots are
always accessible to the program. Any
objects that are reachable from the
roots are considered live. Objects
that are not reachable are considered
garbage, because they can no longer
affect the future course of program
execution.
The garbage collector looks if objects are referenced by live threads. If objects are not reachable by any live threads, they are eligible for garbage collection.
It doesn't matter if the objects are referencing each other.
As others have pointed out, the Java garbage collector doesn't simply look at reference counting; instead it essentially looks at a graph where the nodes are the objects that currently exist and links are a reference from one object to another. It starts from a node that is known to be live (the main method, for instance) and then garbage collects anything that can't be reached.
The Wikipedia article on garbage collection discusses a variety of ways that this can be done, although I don't know exactly which method is used by any of the JVM implementations.
The garbage collector looks for objects that isn't referenced anywhere.
So if you create a object and you loose the reference like the example the garbage collector will collect this.
If I have a linked list structure, and I implement the clear() method as follows:
public void clear() {
firstNode = null;
size = 0;
}
will it still get correctly garbage collected, or would I want to walk through each node, setting nextNode to null?
None of the nodes can be directly referenced from outside the linked list, so there's no case where there would be a reference to any of them outside my class, but I'm unsure if Java would correctly garbage collect the remaining chained nodes.
That should be fine - Java handles cyclic references etc with no problems.
Since none of the nodes of the list have external references. Setting firstNode to null will make all the nodes eligible for GC as there would be no way to reach any of the nodes from an external reference.
for your information, the LinkedList implementation by Sun parse all elements of the list and set them to null