Assigning null to an object with a running method

I have a method, disconnectUser() which among other things, assigns null to an object userSession at the end of execution. However, a hypothetical arose as I was coming up with the logic, where say userSession has a running method and it is assigned a null reference while it is still executing; how does the JVM deal with such a situation?

FWIW here are some code snippets for context:


public class A {
    UserSession userSession;

    /* Skipped irrelevant code
    *-------------------------------
    */

    private void disconnectUser(){
      //Runs an endless while-loop (it's for demonstration's sake)
      userSession.runEndlessLoop();

      userSession = null;
    }
}

ADDENDUM:

Here’s the implementation for runEndlessLoop

public void runEndlessLoop(){
    Executors.newSingleThreadExecutor().execute(() -> while(true){});
}

Answer

userSession is a reference to an object. You “assign” null to this reference, not to an object. So you are changing this reference. It doesn’t change the object userSession formerly referenced / pointed to.

Also see: Can unreferenced objects still run if the garbage collector hasn’t deleted them?

Let me try to add this: If the method of this object is running in the same thread as the rest of your program, the reference would be changed after this method finishes, so the problem doesn’t even come up.
If, in contrast, this object acts in a different thread, well… i just tested it:

public class UnreferencedTest {

    public static void main(String[] args) {
        UnreferencedTest u = new UnreferencedTest();
        u.createObject();
    }

    private void createObject() {

        Unreferenced obj = new Unreferenced();
        Thread t = new Thread(obj);//create new thread
        t.start();
        obj = null;     //remove only reference to object
        System.gc();    //ask GC to clean up

        try {
            Thread.sleep(10000); //wait a bit longer than other thread
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private class Unreferenced implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(5000);
                areYouStillHere();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void areYouStillHere() {
            System.out.println("I'm still here!");
        }
    }

}

… and even “asked” the GC to clean up unreferenced objects. (no guarantee it does!) It’s only waiting for 5 seconds, but still runs.

Hope that helps!

Leave a Reply

Your email address will not be published. Required fields are marked *