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.
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.
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.
Static variables in POJO and garbage collection of objects and classes
No, the static field will not prevent garbage collection of your subclasses (if it did, this would be a major problem, making static fields almost unusable in a garbage-collected language!)
You can test this by adding a finalizer to your classes, then create a bunch of them in a loop, calling System.gc()
to provoke garbage collection.
If your finalize()
method prints out a message, you can see that GC is occurring.
protected void finalize() throws Throwable {
System.out.println("Finalize!");
}
The reason is that the static field belongs to the class object (RepositoryRequest
). This class can't be garbage collected while any of its instances exist, and typically classes aren't unloaded anyway, unless their ClassLoader is garbage collected, which is unusual.
However, all of the memory allocated to each of the instances can be safely reclaimed without having any effect on the class object.
There are situations where static members can prevent GC of other data; for example, if you cache all of the instances of a class in an ordinary Collection as a static field, then they can't be GCd (because there are still 'live' references to them).
static variables as global, and when are static objects garbage collected?
Static variables cannot be eligible for garbage collection while the class is loaded. They can be collected when the respective class loader drops the class or is itself collected for garbage.
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 AppDomain
s 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.
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 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 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 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 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.
Related Topics
Differencebetween Up-Casting and Down-Casting with Respect to Class Variable
How to Add Custom Method to Spring Data JPA
How to Override Class Variables in Java
Obtaining a Powerset of a Set in Java
How to Supply Value to an Annotation from a Constant Java
How to Load a Jar File at Runtime
What Is the "Execute Around" Idiom
Why Should a Java Class Implement Comparable
How Are Spring Data Repositories Actually Implemented
How to Derive Module Descriptor for Auto Generated Module Names in Java 9
How to Use Try-With-Resources with Jdbc
How Does the String Class Override the + Operator
How to Properly Override Clone Method