RedError
RedError

Reputation: 28

Does the garbage collector in Java remove an object if one of its methods is on the call stack?

General question

In Java, there is no reference pointing to an object, but one of the methods of this object is still on the call stack.
Is it possible that the garbage collector removes this object before its method is popped off the call stack, or does it wait until the method is popped off?
(please refer to my specific problem below)

Specific problem

Class structure

Implementation of a simple singly linked list:

Methods of LIST

Code

public class LIST
{
    private LIST_ELEMENT begin = new END();

    // some methods to add or remove elements

    public void clear()
    {
        begin = new END();
    }

    public void insertSorted(DATA_ELEMENT dataNew)
    {
        begin = begin.insertSorted(dataNew);
    }

    public void sort()
    {
        begin.sort(this);
    }
}
public abstract class LIST_ELEMENT
{
    public abstract LIST_ELEMENT insertSorted(DATA_ELEMENT dataNew);
    public abstract void sort(LIST list);
}
public class END extends LIST_ELEMENT
{
    @Override
    public LIST_ELEMENT insertSorted(DATA_ELEMENT dataNew)
    {
        return new NODE(this, dataNew);
    }

    @Override
    public void sort(LIST list)
    {
        list.clear();
    }
}
public class NODE extends LIST_ELEMENT
{
    private LIST_ELEMENT next;
    private DATA_ELEMENT data;

    public NODE(LIST_ELEMENT nextNew, DATA_ELEMENT dataNew)
    {
        next = nextNew;
        data = dataNew;
    }

    @Override
    public LIST_ELEMENT insertSorted(DATA_ELEMENT dataNew)
    {
        if(data.isSmallerThan(dataNew))
        {
            next = next.insertSorted(dataNew);
            return this;
        }
        else
        {
            return new NODE(this, dataNew);
        }
    }

    @Override
    public void sort(LIST list)
    {
        next.sort(list);
        list.insertSorted(data);
    }
}
public interface DATA_ELEMENT
{
    public boolean isSmallerThan(DATA_ELEMENT dataCompare);
}

Question

Having implemented this sorting algorithm, is it safe?
Can the garbage collector remove the data from the NODE objects after the list was cleared (so the call list.insertSorted(data); does something unexpected), or does the method on the call stack count as a reference to the object so that the data attribute is valid for the entire duration of the call of LIST.sort? Is it guaranteed that the object is not removed during this time?

In my testing, the call to LIST.sort always sorted the list as expected.

Upvotes: 0

Views: 1763

Answers (2)

Holger
Holger

Reputation: 298203

It seems, you have a fundamentally wrong understanding of what a garbage collector does. You wrote

Can the garbage collector remove the data from the NODE objects after the list was cleared (so the call list.insertSorted(data); does something unexpected), or does the method on the call stack count as a reference to the object so that the data attribute is valid for the entire duration of the call of LIST.sort? Is it guaranteed that the object is not removed during this time?

A garbage collector will never remove something. A removal is an action in your application logic, like changing the next fields of your node objects. A garbage collector will never perform such actions.

Likewise, the semantics of your “list” do not affect the garbage collector. To the garbage collector, an instance of your LIST class is just an object with a reference to another object. When the garbage collector decides to reuse the memory of the LIST instance, it does not affect the LIST_ELEMENT you might be still working on. It does not collect “the entire list”, as to the garbage collector, there is no such thing as a list.

As a simple rule of thumb, unless you write code with a special interaction with the garbage collector, like a finalizer or cleaner, or are dealing with the special weak, soft, or phantom reference objects, you will never notice the garbage collector’s activity. It will reuse the memory of those objects whose memory is not needed by the application, in other words whenever your application won’t notice it.

That said, contrary to the other answers, executing an instance method does not prevent the garbage collection of an object that is otherwise unused. But how could it be otherwise unused? That would imply that even the caller has no other reference to the list (or won’t use it). So who cares about the contents of the list, if no reference to the list exist? The other scenario would be that the JVM has optimized the code such that it doesn’t need the memory of the object, e.g. because it keeps all field values in CPU registers. You would again not notice anything, as the behavior of the program remains the same.

A real-life example has been documented in finalize() called on strongly reachable objects in Java 8 where an object truly got finalized while a method invocation on the object was ongoing. But as said, such things can only have a perceivable effect on the application’s behavior when you interact with the garbage collector explicitly. In the linked Q&A, it was a finalizer producing a noticeable effect.

Upvotes: 3

mentallurg
mentallurg

Reputation: 5207

In Java, there is no reference pointing to an object, but one of the methods of this object is still on the call stack.

This cannot happen. If a method is running, there is a reference to an object whose method was called.

Is it possible that the garbage collector removes this object before its method is popped off the call stack, or does it wait until the method is popped off?

As long as method is running, there is a reference to the object. That's why such object cannot be removed.

Upvotes: 1

Related Questions