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?
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:
new Activity();
//or
Activity a = new Activity();
a = null;
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.
B b = new B();
b.referenceField = Activity.objectStatic;
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.
Activity a = new Activity();
B b = new B();
b.referenceField = a.objectStatic;
a = null;
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
)
Activity a = new Activity();
C c = new C();
c.primitiveField = a.primitiveStatic;
a = null;
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With