How to circumvent the static initializer size limit in Java when initializing large numbers of constants

I have a class containing a large number of constants created 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 constants generated is very large, this leads to a static initializer that is greater than the upper limit for the size of the Java method (i.e.> 64 kB), which leads to a compiler error. One solution is to create several โ€œblock initialization methodsโ€ for blocks that can be guaranteed to create less than 64 KB of byte code, so that they fit into the 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 disadvantage of this is that I can no longer declare constants as final , because now they are no longer initialized directly in the static initializer.

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

+6
source share
4 answers

Finally, I went for a solution that included nested classes. This was suggested in the comment on this answer here by the user of Loadmaster . Nested classes have two advantages:

  • They allow you to hide these details of implementing workarounds from the outside world, being private nested classes
  • They allow you to save final constants

But they also have a drawback compared to templatetypedef :

  • I will again face the same problem with a lot more constants

However, now this is 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 ... {} } 
+1
source

One option is to use inheritance - to have a series of classes Constants1 , Constants2 , ..., ConstantsN , so that everyone defines constants, and then each of them inherits from the previous one. The final Constants class can then be directly inherited from the last of them. It also allows you to mark everything final .

Out of curiosity, how did you get into such a large file that you could not substitute the initialization code in the limit of 64 KB?

Hope this helps!

+7
source

Would it work? NO See comments why this answer will not solve the problem.

This will allow you to keep the static variables final, and it would be easier to auto-generate. However, java collapses all static init blocks into one giant static init block, and therefore the problem is not resolved.

 public class Constants extends SomeBaseClass { // init() is defined in some base class... public static final XXX KEY1 ; static { KEY1 = init(...); } public static final XXX KEY2 ; static { KEY2 = init(...); } public static final XXX KEY3 ; static { KEY3 = init(...); } // ... } 
0
source

You can have as many static initialization blocks as you want.

-1
source

Source: https://habr.com/ru/post/917133/


All Articles