Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an activity be garbage collected if it has static member variables who are referenced elsewhere?

Suppose an Activity A has some static member variables, since statics are loaded in memory when class is first loaded by VM and stays around, I wonder what happens to Activity with respect to garbage collection if other class B is holding any static variable of class A.? Will it not be collected? Will it be collected and statics are initialized to initial values?

like image 281
rahil008 Avatar asked Dec 19 '22 00:12

rahil008


1 Answers

Classes for example purposes

public class Activity {
    public static int primitiveStatic = 42;
    public static Object objectStatic = new Object();
}

public class B {
    public Object referenceField = null;
}

public class C {
    public int primitiveField = 0;
}

A simple model of a Java object instance is a memory area containing, in addition to space for each of its instance members (non-static), some administrative information including a reference to its class object. The class object (the entity in memory at runtime) contains various pieces of information about the class, including (relevant to this question) space for each of the static members of the class. Note that some of this is JVM dependent.

The key thing to note is that static members are stored in or with the class object at runtime (not in any instance object).

In the example classes above, the Activity class object at runtime would have two variables, one primitive integer variable (primitiveStatic) and one reference of Object type (objectStatic). Every instance of the class would have its own distinct memory area, containing not much more than a single reference to the class object. An instance of B has space for a single object reference. An instance of C has space for a single primitive integer value.

The garbage collector can remove and finalize any object in memory which is eligible for collection. This does apply also to class objects, but it is not as simple as for instance objects, where the object is eligible if there are simply no references to it. Class objects and static fields are rarely eligible, but in cases where the class is unloaded, they are. See this documentation for more information on class unloading.

I believe the cases you are wondering about include these:

Case 1

new Activity();
//or
Activity a = new Activity();
a = null;

Case 1 setup

Case 1 after set up and assignments are completed.

The class is loaded, creating the class object and static variables as described above. An instance is created, as described above. The instance is immediately eligible for garbage collection. When collected, the instance is destroyed, removing the reference to the class object. If it is the end of the program or in other certain cases, the class object may also be garbage collected, removing the primitiveStatic and objectStatic variables. In this case, the new Object() which was referred to by objectStatic now also has no references to it, and is in turn eligible for garbage collection in the normal way.

Case 2

B b = new B();
b.referenceField = Activity.objectStatic;

Case 2 setup

Case 2 after setup and assignments are completed.

A new B instance is created (and the class object for class B) as described above. The Activity class is loaded and class object created if it has not been already. The referenceField in b is set to refer to the same location as the objectStatic field, which is found in or with the Activity class object. If the Activity class is unloaded (happens in some cases but not common), its class object is removed as described in //1. This time, the new Object() still has a reference to it, in b.referenceField, so is not eligible for collection. We are left with the B class object and the new Object() and an instance, b, with a single reference to each.

Case 3

Activity a = new Activity();
B b = new B();
b.referenceField = a.objectStatic;
a = null;

Case 3 setup

Case 3 after setup and assignments are completed.

The Activity class is loaded, and class object created if they aren't already, as described above. An instance is created, as described above. The same for the B class. By finding a's class reference and locating it there, the static reference objectStatic is obtained from a and assigned to b.referenceField. This is a copy assignment of the reference value, so there is no reference between b and a or Activity, but b now contains a reference to the new Object() constructed by the Activity class. a = null means that the Activity instance initially referred to by a becomes eligible for garbage collection. Its reference to the Activity class object is removed. The Activity class object may become eligible for garbage collection. If it is, the static fields it contains are cleared. The new Object() referred to by objectStatic now has a single reference, in b, so is not eligible for garbage collection. We are left with this object, and the B class object, and b which contains a single reference to each (identical to case //2)

Case 4

Activity a = new Activity();
C c = new C();
c.primitiveField = a.primitiveStatic;
a = null;

Case 4 setup

Case 4 after setup and assignments are completed.

Like in //3, the Activity class is loaded, and class object created if they aren't already, and an instance is created, as described above. The same for the C class. By finding a's class reference and locating it there, the static primitive primitiveStatic is obtained from a and assigned to c.primitiveField. This is simply a copy assignment, so there is no reference between c and a or Activity. a = null means that the Activity instance initially referred to by a becomes eligible for garbage collection. Its reference to the Activity class object is removed. The Activity class object may become eligible for garbage collection. If it is, the static fields it contains are cleared. The new Object() referred to by objectStatic now has no references, so is eligible for garbage collection. We are left with the C instance, c, with a primitive int value of 42 in its primitiveField.

In all of these cases, no object instance is prevented from being garbage collected by something else having references to objects also referred to by its class static fields (and even the class and its static values can be garbage collected in certain circumstances), even when those field values are 'owned' by the class (e.g. final and initialised in and by the class.)

Things to watch out for are that if the objectStatic field is final, the object it refers to will almost never be collected: the Activity class must be unloaded for it to become eligible for collection. This could be a problem if you have lots of static object references which are not used after program setup, since they will stick around and fill up memory even though they aren't used.

like image 91
Oly Avatar answered Dec 25 '22 22:12

Oly