1

If i have class A and B. Then A has object of B as below and B has reference to A.

class A extends Activity{
    private B objectB;
    public A(){
        objectB= new B(this);
    }
}

class B{
    private A objectA;
    public B(A a){
        objectA= a;
    }
}

When A class is destroyed, its variable objectB should be destroyed as well. So what happens to objectA ? Does it still hold reference to A even objectB is destroyed? Or A will not be Garbage Collected even it is destroyed since objectA holds reference to it? On this issue, similar case happens and it is considered as memory leak.

Jemshit
  • 9,501
  • 5
  • 69
  • 106

2 Answers2

3

In the example code above, there is circular reference between Aand B classes. These will be garbage collected IF they are not reachable by any other object instance in Application.

"Activityis destroyed" does not mean it is garbage collected. But when Activity is garbage collected, its variables, Views, which only Activity references to, will be garbage collected as well. I think, on onDestroy() of Activity class, variables will be assigned to null but still their values will be held on memory until they are garbage collected.

In the link written in question, Presenter object had reference to Activity and vice versa. They would be garbage collected if they were not referenced by other object instances in Application. But Activity is referenced by Presenter which is referenced by Subscriptionobject, which is also referenced by some static class.

Same rules apply to when creating Adapter and passing Context from Activity. If they both are not referenced by other objects, there will not be a leak. But to be cautious, you should pass Application Contextto Adapterinstead of Activity Context.

Community
  • 1
  • 1
Jemshit
  • 9,501
  • 5
  • 69
  • 106
1

It would depend on if the object references in A and B are the same object references within each other. After you edited the example to include how A and B were instantiated (newed up), there IS NOT a memory leak in your example because the instances created of each are not the same instances (different memory reference).

It would be possible to create a memory leak in a case like this, depending on how the two classes are constructed or instantiated. The definition of the classes given above doesn't have enough information to determine if a memory leak is present.

For example, given the following class definitions:

    class A extends Activity{
        private B objectB;

        public void setB(B b){
            objectB = b;
        }
    }

    class B{
        private A objectA;

        public B(A a){
            objectA = a;
        }
    }

If you then created a Test class instantiating A and B as shown here:

    class Test(){
        public static void main(String... args){
            A a = new A();
            B b = new B(a);
            a.setB(b);
        }
    }

In this case, a memory leak has been introduced because as B is instantiated, it is passed a reference to A and then we explicitly set B in A to the same B holding a reference to this instance of A.

If we change the code in Test by one line:

    class Test(){
        public static void main(String... args){
            A a = new A();
            B b = new B(a);
            a.setB(new B()); //Modified this line
        }
    }

Now we no longer have a memory leak, as the B we pass to A is not the same instance as the B holding a reference to A.

pczeus
  • 7,709
  • 4
  • 36
  • 51
  • added how objects are instantiated – Jemshit Feb 20 '16 at 14:22
  • The first example is my case, so why there is leak? – Jemshit Feb 20 '16 at 14:25
  • 2
    That is not a memory leak. – pczeus Feb 20 '16 at 14:26
  • If however, your example was modified in class A to pass the 'this' to B's constructor when creating B and B had a constructor accepting A, then you would have a memory leak. That is the example I show in my answer. – pczeus Feb 20 '16 at 14:29
  • Realize the garbage collector, the one responsible for freeing up memory doesn't care that you have multiple places in your code using the same type of objects. It will only free up memory and destroy an object instance IF there is no object in memory that refers to that exact instance of the object. – pczeus Feb 20 '16 at 14:32