8

Once a class is loaded is there a way to invoke static initializers again?

public class Foo {

    static {
        System.out.println("bar");
    }

}

Edit:

I need to invoke the static initializer because I didn't write the original class and the logic I need to invoke is implemented in the static initializer.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Kalecser
  • 1,143
  • 12
  • 15

6 Answers6

10

Put the initalisation code in a separate public static method, so you can call it from the static initializer and from elsewhere?

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • I can't modify the code. It's in a third party library and I don't intend to create my own distribution of it with the code in a regular static method. :) The solution I've used was to copy and paste the code in another class so it can be in a regular static method. But I didn't like it. DRY – Kalecser Mar 26 '09 at 16:31
  • Hm... then my next question is, why does that 3rd party class have logic in a static initializer that you might want to reinvoke?! – Daniel Earwicker Mar 26 '09 at 16:59
  • It will load and process an XML config file on the static initializer, i want to reload the xml. – Kalecser Mar 26 '09 at 17:32
  • The static initilizer has 70 + LOC. – Kalecser Mar 26 '09 at 17:33
  • Ugh... you have my sympathy! :) – Daniel Earwicker Mar 26 '09 at 18:00
5

One circumstance in which the logic would be run more than once is if the class is loaded multiple times by different ClassLoaders. Note that in this instance, they are essentially different classes.

Generally, though, these are one-shot deals. If you want to be able to invoke the logic multiple times, do as others have suggested and put it in a static method.

McDowell
  • 107,573
  • 31
  • 204
  • 267
  • 1
    I was trying to find a reference about classloaders but couldn't find a good one. Do you have one? – Michael Myers Mar 25 '09 at 18:32
  • 1
    Alas, no. My knowledge is cobbled together from the VM spec, the javadoc, server manuals and various internet sources. You could do worse than Googling "developerWorks" and "ClassLoader". – McDowell Mar 25 '09 at 18:57
  • The answer here has a small class loader example: https://stackoverflow.com/questions/33040829/java-static-initializer-called-twice – KANJICODER Jul 10 '18 at 19:57
4

I agree with Earwicker's answer. Just extract the static initialization to a separate static method.

public class Foo {

    static {
        Foo.initialize();
    }

    public static void initialize() {
        System.out.println("bar");
    }

}
bruno conde
  • 47,767
  • 15
  • 98
  • 117
2

In case you really want the exact answer to your exact question, the answer is no. It's not possible to invoke a static initializer or an instanceInitializer via reflection.

The docs clearly says :

for getDeclaredMethod(String name) :

If the name is "<init>" or "<clinit>" a NoSuchMethodException is raised.

for getDeclaredMethods() :

The class initialization method is not included in the returned array.

So no, it's not possible to invoke it, even via reflection.

Snicolas
  • 37,840
  • 15
  • 114
  • 173
0

Here https://stackoverflow.com/a/19302726/2300018 is a post from me, where I re-load a utility class to re-run the static initializer for unit testing.

Community
  • 1
  • 1
André
  • 308
  • 2
  • 17
0

you could try extending the class which contains the static code, and then put in your own static initializer. Not quite sure if it works, but :

public class OldBadLibraryClass {
   static {
      System.out.println("oldBadLibrary static init");
   }
}

//next file

public class MyBetterClass extends OldBadLibraryClass {
   static {
      System.out.println("MyBetterClass init");
   }
}


public class Test {
   public static void main(String[] args) {
      new MyBetterClass();
   }
}

see if the above prints in the order you expect. On my machine, it worked.

Though this is totally a hack, and is quite brittle. It would really be much better to modify the old class to have an init() method that can be overridden.

Chii
  • 14,540
  • 3
  • 37
  • 44