[Effective Java] Article 6: Eliminate expired object references

When you jump from a language that requires memory management ( C, ) to a language based on managing memory, you will find that it is much simpler. It frees up your work because unavailable objects are automatically reclaimed.C++GCGC

But does GCmanaging memory have to be reliable? The answer is not necessarily. Such as:

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);
    }
}

The above is a simple Stacksimulation. If you test, you will find that any operation is possible. But there is a shortcoming: when the data on the top of the stack is fetched, the data on the top of the stack is not emptied, so that the GCspace on the top of the stack cannot be reclaimed. Such repeated insertion and retrieval of data may eventually lead to OutOfMemoryError.

How to modify it?

Very simple, just empty the top element of the stack. which is:

public Object pop() {
    if (size == 0)
        throw new EmptyStackException();

    Object result = elements[--size];
    //消除过期对象引用
    elements[size] = null;
    return result;
}

Isn't that a little suspicious? Do we need to empty objects that we don't need to use in the future? The answer is no. Nulling objects should be the exception, not the norm , or GCsuperfluous.

In fact, when the class needs to manage its own memory, it only needs to eliminate the reference to the expired object. Developers should be wary of memory leaks. Usually such a class is often associated with an array. At the beginning, the data is stored in the array, and then it is fetched (unavailable), but GCthe fetch operation at this time is not understood, because the data is still stored in memory, only the developer knows this. The fetch is to make the data unavailable, so the developer needs to give a GChint.

Another common source of memory leaks is cache. Because once you store data in the cache and do not clean it up in time, it is equivalent to a memory leak.

Listeners and callbacks are also responsible for memory leaks. If there is one API, and the client is injecting callbacks into it, but there is no explicit unregister, then unless you cancel with some action, it will keep accumulating until memory overflows.

GCMemory leaks are very hard to spot in a based language. Usually can only rely on careful inspection of the code, or with the help Heap Profilerof tools to check.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325950088&siteId=291194637