javacompiler-errorsstatic-initialization

How to circumvent the size limit of a static initialiser in Java when initialising large amounts of constants


I have a class holding a large a mount of generated constants as such:

public class Constants extends SomeBaseClass {

  // init() is defined in some base class...
  public static final XXX KEY1 = init(...);
  public static final XXX KEY2 = init(...);
  public static final XXX KEY3 = init(...);

  // ...
  public static final XXX KEY2000 = init(...);
}

When the number of generated constants is very high, this results in a static initialiser that is larger than the upper limit for Java method sizes (i.e. > 64kb), resulting in a compiler error. One solution is to create several "block initialisation methods" for blocks that can be guaranteed to produce less than 64kb of byte-code, such that they fit into a method:

public class Constants extends SomeBaseClass {

  public static XXX KEY1;
  public static XXX KEY2;
  public static XXX KEY3;

  // ...
  public static XXX KEY2000;

  static {
    initialise0001To1000();
    initialise1001To2000();
  }

  private static void initialise0001To1000() {
    KEY1 = init(...);
    KEY2 = init(...);
    KEY3 = init(...);
    // ...
  }

  private static void initialise1001To2000() {
    // ...
    KEY2000 = init(...);
  }
}

The drawback of this is that I can no longer declare the constants as final, because they are now no longer initialised directly in the static initialiser.

My question is, how can I circumvent that compiler / JVM limitation in a way that I can still generate static final constants?


Solution

  • I finally went for a solution involving nested classes. This was suggested in a comment to this answer here by user Loadmaster. Nested classes have two advantages:

    But they also have a disadvantage compared to templatetypedef's solution:

    Right now, however, this seems to be the most suitable solution:

    public class Constants {
    
      public static XXX KEY1    = Constants1.KEY1;
      public static XXX KEY2    = Constants1.KEY2;
      public static XXX KEY3    = Constants1.KEY3;
    
      // ...
      public static XXX KEY2000 = Constants2.KEY2000;
    
      // Nested class holding 1000 constants
      private static class Constants1 extends SomeBaseClass {
        KEY1 = init(...);
        KEY2 = init(...);
        KEY3 = init(...);
        // ...
      }
    
      // Nested class holding the next 1000 constants
      private static class Constants2 extends SomeBaseClass {
        // ...
        KEY2000 = init(...);
      }
    
      // Keep generating nested classes for more constants...
      private static class Constants3 ... {}
    }