Yati Sawhney
Yati Sawhney

Reputation: 1402

Why does an inner class instance remian in the memory even if the outer class object is destroyed?

Please consider following two classes:

a.) Student

package datatypes;

public class Student {

    private String name ;

    public Student(String name) {
        this.name = name;
    }

    class Address{
        String city;
        String state;

        Address(String city , String state){
            this.city = city;
            this.state = state;
        }

        String getAddress(){
            return city + state;
        }

    }

    String getName(){
        return name;
    }
}

b.) StudentDemo

package datatypes;

import datatypes.Student.Address;

public class StudentDemo {
    public static void main(String[] args) {
        Student obj = new Student("Yati");
        Address adr = obj.new Address("YNR" , "HARYANA");

        System.out.println(obj.getName());
        System.out.println(adr.getAddress());

        obj=null;

        //System.out.println(obj.getName());
        System.out.println(adr.getAddress()); //Line 16

    }
}

According to oracle java docs

For creating an instance of the inner class first we have to create an instance of the enclosing class and later we can create the instances of the inner class.

Like other members (instance variables and instance methods) inner class is also a member of the instance of the outer class. In line no 16 of StudentDemo.java I am still able to print the value of the address even if the object which was responsible for the creation of Address object DOES NOT exist in the memory.

My question is: why does the Address object remains in the memory and doesn't get destroyed automatically once the obj is set to null?

Output:

Yati
YNRHARYANA
YNRHARYANA

Upvotes: 2

Views: 877

Answers (4)

GhostCat
GhostCat

Reputation: 140457

Setting a reference to null does not mean that the garbage collector immediately collects the corresponding object from memory!

And beyond that: the GC can't even collect your object; because adr still has a reference to the "inner object"; and that one has a reference to its outer owner!

So, even when you would add a System.gc() call after doing obj = null ... that object can not be collected. (and just for the record: calling gc() is just a "hint" to the JVM to run the garbage collector; there are no guarantees that anything happens)

Long story short: of course things have to work this way. Your code holds a reference to an inner object; and while that reference is there, that object must exist. And while that inner object must exist; so must its outer parent. In other words: the whole system relies on the fact that the life time of inner/outer objects are tightly coupled!

And given your last comment - how is the runtime supposed to know that this inner object could live with its outer parent being null?! You might call a method on inner that actually uses outer.this; and then what, NullPointerException?!

So the real answer might be to understand that you asking a purely theoretical questions. In the "real" world you would simply not do that. In the real world, you would not hand out references to inner objects; not caring about their outer parent. Similar to Domain Driven Design - there an aggregation of objects is also only accepted via the root object of the aggregation (see here for example). That is of course not the same as objects within the JVM; but as said: an example that you simply do things differently for conceptual reasons.

Upvotes: 7

Alexey Romanov
Alexey Romanov

Reputation: 170745

if the object which was responsible for the creation of Address object DOES NOT exist in the memory

Of course it does: it's referenced from adr, and adr is accessible, so it can't be garbage-collected. Even if it wasn't referenced, it wouldn't necessarily be collected immediately.

Upvotes: 1

Jean-Baptiste Yunès
Jean-Baptiste Yunès

Reputation: 36401

An object is eligible for destruction when there is no more reference to it or there is no more reference to any object in the graph of reference it participates in. Two simple cases:

(o) a single "lost" object

(o1) <- (o2) two "lost "objects"

In the second case, if you have a reference on (o1) then (o1) is not lost but (o2) is.

An inner object has a reference to its enclosing outer object, and as you have a reference to the inner object, then there exists a "living" reference to its outer object. You have something like:

(outer <- (inner) <-)----some reference

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234715

Aside from the fact that a reference to your inner class is still in use, all your inner and outer class shenanigans are red herrings.

The fact remains that writing

Foo f = new Foo();
f = null;

for any class Foo, will merely cause the created instance of Foo to be scheduled for garbage collection. The object will not necessarily be destroyed immediately.

Upvotes: 3

Related Questions