Do Static Members Ever Get Garbage Collected

Are static fields open for garbage collection?

Static variables cannot be elected for garbage collection while the class is loaded. They can be collected when the respective class loader (that was responsible for loading this class) is itself collected for garbage.

Check out the JLS Section 12.7 Unloading of Classes and Interfaces

A class or interface may be unloaded
if and only if its defining class
loader may be reclaimed by the garbage
collector [...] Classes and interfaces
loaded by the bootstrap loader may not
be unloaded.

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

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.

Do static members ever get garbage collected?

No, static members are associated with the Type, which is associated with the AppDomain it's loaded in.

Note that there doesn't have to be any instances of HasStatic for the class to be initialized and the shared variable to have a reference to a List<string>.

Unless you're considering situations where AppDomains get unloaded, static variables can be regarded as GC roots forever. (Of course, if something changes the value of HasStatic.shared to reference a different instance, the first instance may become eligible for garbage collection.)

Garbage collection of static members

Objects referenced by static variables will only be garbage collected when the relevant AppDomain is garbage collected. In client applications, there's often just a single AppDomain which lives for the duration of the process. (An exception is when the application uses a plug-in architecture - different plug-ins may be loaded in different AppDomains and the AppDomain may be unloaded later.)

In ASP.NET, "AppDomain recycling" happens periodically (for various reasons) - when this occurs, and the static variables within that AppDomain will no longer act as GC roots, and thus won't prevent objects being garbage collected.

If you were worried about an object being garbage collected while you still had a reference to it via a static variable, though, you can relax. While you can access the object, it won't be garbage collected.

Are dereferenced static variables garbage collected?

Variables aren't garbage collected, and aren't dereferenced either. Objects are garbage-collected, maybe, if there are no references. static really has nothing to do with it.

EDIT

Okay I think I get it.

Let's see.

There are no static objects per se, there are static references.

Correct.

Static references persist throughout the application life-cycle, and are never garbage collected.

Incorrect. Static references are held in class objects. Those class objects can be garbage-collected under some circumstances. It is meaningless to speak of references being garbage-collected.

Therefore, any object they point to will not be garbage collected.

There is no 'therefore' about it. An object is eligible for garbage-collection when there are no more references to it. Zero. One object containing a reference to it being garbage-collected is necessary but not sufficient. There have to be no other references, and the garbage-collector has to actually reach the object.

Additionally, all non-static references that go out of scope will be garbage collected.

Incorrect. It is meaningless to speak of references being garbage-collected.

Is my understanding correct?

No.

Does the garbage collector work on static variables or methods in java?

static fields are associated with the class, not an individual instance.

static fields are cleaned up when the ClassLoader which hold the class unloaded. In many simple programs, that is never.

If you want the fields to be associated with an instances and cleaned up then the instance is cleaned up, make them instance fields, not static ones.

Can garbage collector run on Static class objects

Short answer : No. Marking your class static may NOT save it from garbage collection

Making a class static may avoid garbage collection for the particular class loader which was responsible for loading it. However, if this classloader gets opted for garbage collection, then all classes loaded via it ( static or non-static ) will also be garbage collected.

Usually this is the case when you have multiple class loaders in your application.

Other than that, an object ( any object ) is opted for garbage collection when it becomes unreachable

From the JLS (source)

A class or interface may be unloaded if and only if its defining class loader may be reclaimed by the garbage collector [...] Classes and interfaces loaded by the bootstrap loader may not be unloaded.



Related Topics



Leave a reply



Submit