Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does referencing array index creates a memory leak?

I am reading "Item 6: Eliminate obsolete object references" of Effective Java second edition.

Below is the code snippet.

//Can you spot the "memory leak"?
public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        return elements[--size];
    }

    /**
     * Ensure space for at least one more element, roughly doubling the capacity
     * each time the array needs to grow.
     */
    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }
}

As per this item, memory leak is because after popping, array index was not referenced to NULL like below:

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();
    Object result = elements[--size];
    elements[size] = null; // Eliminate obsolete reference
    return result;
}

My understanding have been that suppose for an given array, I have done elements[0] = new Object() and then I do this again elements[0] = new Object() then my first object would be eligible for garbage collection because 0th index of my array is no more pointing to it.

Is my understanding incorrect? If it is correct then how it is shown as memory leak in Effective Java.

like image 928
pjj Avatar asked Jun 15 '26 00:06

pjj


1 Answers

You got most of it.

If you do:

elements[0] = someOtherObject;

then the other element stored at index 0 is no longer referenced and might be collected.

But the first pop() implementation keeps that reference in place - it only decreases the "counter" of stored elements. Therefore that object is still referenced - and won't be collected until a new object is added to the stack!

As the comment in the second version of pop() clearly states - the reference has to be eliminated to ensure that the stack doesn't keep a reference to that very object. The object is supposed to be popped - so the stack should not keep knowledge about that removed object!

And to confirm the commit: yes, when one pushes n object, then pushes n other objects, then you don't have a memory leak - because the underlying array references will all be updated and point to new objects then. And yes, if less than n objects get pushed after popping, stale references are kept and preventing garbage collection here.

like image 89
GhostCat Avatar answered Jun 16 '26 15:06

GhostCat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!