102

Given an hypothetical utility class that is used only in program setup:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

will myObject be garbage collected when it is no longer being used, or will it stick around for the life of the program?

Michael Deardeuff
  • 10,386
  • 5
  • 51
  • 74

6 Answers6

127

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.

bruno conde
  • 47,767
  • 15
  • 98
  • 117
  • @bruno, Per your link, does it mean that a class loader hold a reference to each and every class it loads, even if the class loaded doesn't have static members? – Pacerier Aug 23 '14 at 07:07
  • @brunoconde, I don't think that's true actually. Exactly which paragraph states that? (Please continue the discussion on http://stackoverflow.com/questions/405364/whats-up-with-static-memory-in-java/405402?noredirect=1#comment39739557_405402 ) – Pacerier Aug 24 '14 at 11:10
  • 2
    When the class loader would be eligible for garbage collection. ? – Rohit Bandil Sep 15 '16 at 13:28
  • 1
    @RohitBandil - when it is unreachable. – Stephen C Jan 21 '18 at 03:16
  • @StephenC what if it's a class containing only static fields/methods, i.e. a class that is never instantiated? – reidestis Jul 20 '22 at 15:51
  • 1
    @reidestis - the answer is the same. Static fields can only be unreachable if the class is unreachable, and that can only happen if its classloader is unreachable as well. – Stephen C Jul 20 '22 at 23:15
  • @Bruno: "A class or interface may be unloaded" -- here by unloading it mean GC of object of `java.lang.Class` or the metadata of that particular class present on metaspace/permgen? – hagrawal7777 Dec 18 '22 at 05:18
65

Static variables are referenced by Class objects which are referenced by ClassLoaders -so unless either the ClassLoader drops the Class somehow (if that's even possible) or the ClassLoader itself becomes eligible for collection (more likely - think of unloading webapps) the static variables (or rather, the objects they reference) won't be collected.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Do `Class` objects that contain no static variables get referenced by their class loader? – Pacerier Aug 23 '14 at 05:35
  • @Pacerier: yes. – hagrawal7777 Dec 18 '22 at 05:15
  • @Jon: " referenced by Class objects which are referenced by ClassLoaders" -- here you mean object of `java.lang.Class` or the metadata of that particular class present on metaspace/permgen? – hagrawal7777 Dec 18 '22 at 05:16
  • 1
    @hagrawal: Yes, objects of type `Class` - they may not reference the data directly, in that there may well be some internals; but they're clearly able to access the data somehow. – Jon Skeet Dec 18 '22 at 07:50
15

myObject is a reference and not an object. An object is automatically garbage collected when no reference points to it because it is unreachable.

So also the object behind a static reference "myObject" can be garbage collected if you dereference it with

myObject = null;

and there are no other references to this object.

However static references and variables remain for the lifetime of your program.

Felix Keil
  • 2,344
  • 1
  • 25
  • 27
  • Welcome to StackOverflow! Setting the object to `null` at the end of the `static block` is a viable option. In my case, though, the object's lifetime needed to be longer than the static block. The object's end-of-usefulness was not very concrete; thus my ask about utilizing the garbage collector. – Michael Deardeuff Jul 11 '14 at 16:46
14

If you want a temporary object to be used for static initialisation then disposed of, you can use a static initialiser block, e.g.

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

since the static initialiser block is a special kind of static method, myObject is a local variable and can be garbage collected after the block finishes executing.

finnw
  • 47,861
  • 24
  • 143
  • 221
7

I think this answers your question - basically not unless the class comes from a special class loader and that unloads the class.

Community
  • 1
  • 1
Tom
  • 43,583
  • 4
  • 41
  • 61
0

The key here is the Garbage Collection of Class instances i.e. Objects. ClassLoader instance is, in essence, an Object. So if the Classloader object is not garbage collected, any references of them stored in heap (i.e. static stuff) will almost never be garbage collected. The exception is String pool.

So before you suddenly decide to do private static MyGiantClass myGiantObject = new MyGiantClass() Think twice as I have learnt the hard way.

ha9u63a7
  • 6,233
  • 16
  • 73
  • 108