简体   繁体   中英

Garbage Collection in 2.1 Cracking the Coding Interview

For this block of code (solution for 2.1 in Cracking the Coding Interview): when you do prev.next = n.next , would n get collected by garbage collector? Then how can you do n = n.next ?

The 2.1 question is: write code to remove duplicates from an unsorted linked list.

Can someone explain to me how garbage collector works in this case?

public static void removeDup (LinkedListNode del)
{
    LinkedListNode prev = null;
Hashtable myTable = new Hashtable();

    while(del!= null)
    {


        // table does not have the key yet
        if (myTable.containsKey(del.data) == false)
        {
            myTable.put(del.data, true);
            prev = del;
        }

        // table has the duplicate
        else 
        {
            prev.next = del.next;
        }
        del = del.next;
    }
}

When you call prev.next = n.next; , n is still immediately available as a variable in your method. It's not going anywhere, it's in the prime of its life. Objects will only get garbage collected when there was absolutely no way for you to access them anyway.

If you were to immediately follow that up with n = null; , then sure, the object n was pointing to will probably be garbage collected (assuming you don't have it stored anywhere else). Not right away mind you, but eventually. The point is, it doesn't matter when the garbage collection happens because you no longer have any way to get a reference to that object back into your code.

As to the garbage collector, when you write

 del = del.next;

whatever was previously referenced by del, (assuming nothing else is referencing it) is eligible to be garbage collected - if the variable del is the only thing referencing that data, once del is reassigned nothing is referencing that data anymore, which makes it eligible for GC. Note that this does not mean it will immediately be GC'd.

BTW, in your code, where you write

else 
    {
        prev.next = del.next;
    }

you're going to get a NullPointerException , since you're trying to access a member of prev, which has been set to null above.

You are reassigning del in your method as del = del.next; . So the older del maybe eligible for garbage collection, if there is no other reference pointing to del either directly or indirectly.

Objects are garbage collected when the object goes out of scope and no other reference is pointing to that object.

I feel like, it's easier to understand if we take a simple case, and walk through what's happening (in a simple manner, actual implementation is likely using counters, and more complex data structures but I digress). Let's say we have a linked list of 1 -> 1 -> 2 -> null passed to this method, and take a look at what is on the stack and on the heap at the point just before we get into the while loop for the first time:

Heap: { 
  #1 : { LLN, data: 1 , next #2    }, 
  #2 : { LLN, data: 1 , next #3    }, 
  #3 : { LLN, data: 2 , next: null },
  #4 : { HashTable, keyvalues: {} } 
}
Stack : {
  del: #1
 prev: null
 myTable: #4
}

Omitted from this picture is the local variables on the stack for the calling function all the way back up to the top of the chain of course, and any other objects that are allocated that we don't know about.

Also we know that an object (allocated on the heap) becomes eligible for garbage collection when it becomes unreachable by any code. Or in other words: If it is impossible for me to start with references on the stack, and follow references on the heap to get to a particular location, it's eligible to be cleared out by the garbage collector.

Let's make one iteration through the while loop (you should wind up with this):

Heap: { 
  #1 : { LLN, data: 1 , next: #2    }, 
  #2 : { LLN, data: 1 , next: #3    }, 
  #3 : { LLN, data: 2 , next: null  },
  #4 : { HashTable, keyvalues: {1:true} } 
}
Stack : {
  del: #2
 prev: #1
 myTable: #4
}

Still we see everything is reachable, as before. Let's step into the second iteration, we wind up on the else block, and perform do: prev.next = del.next . Since del.next = #3, and we assign prev.next that value and wind up with this:

Heap: { 
  #1 : { LLN, data: 1 , next: #3    }, 
  #2 : { LLN, data: 1 , next: #3    }, 
  #3 : { LLN, data: 2 , next: null  },
  #4 : { HashTable, keyvalues: {1:true} } 
}
Stack : {
  del: #2
 prev: #1
 myTable: #4
}

At this point you can see that everything is still alive on the heap (not eligible for garbage collection). #1 is referenced by prev, #2 by del, #4 by myTable, and #3 through both #1 and #2 which are both alive. Now watch what happens when I do del = del.next :

Heap: { 
  #1 : { LLN, data: 1 , next: #3    }, 
  #2 : { LLN, data: 1 , next: #3    }, 
  #3 : { LLN, data: 2 , next: null  },
  #4 : { HashTable, keyvalues: {1:true} } 
}
Stack : {
  del: #3
 prev: #1
 myTable: #4
}

Nothing (known) on my stack points now points to number #2, therefore it could be eligible for garbage collection at this point. As I mentioned before, we don't know the rest of the stack, therefore something else might have a reference to it, however more than likely it's dead and can be reclaimed. As others have already mentioned garbage collection doesn't have to happen at this point, but if it does, and nothing else is holding a reference to #2, it could reclaim #2.

If you continue this exercise you'll notice that on the next iteration of the while loop, #1 will also no longer be referenced by anything we know about from the stack. However it's more than likely the method calling this method has a local variable with a reference to #1 so it probably wouldn't become eligible for garbage collecting then.

This is of course a very simplified walking through of what is happening, but it's the jist of things. If you're interested, you should also look into how finalizers play into when memory is actually reclaimed. Soft and Weak References are also very interesting topics as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM