Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jooq/Java Constant pool 64K limit

Tags:

java

class

jooq

Quote from the Jooq manual :

Turning off the generation of the above files may be necessary for very large schemas, which exceed the amount of allowed constants in a class's constant pool (64k) or, whose static initialiser would exceed 64k of byte code

I do understand the issue, but how do one measure or plan for this. Does anybody have a good estimate of how many tables with how many columns per table of a reasonable average name length this is? I really do appreciate the fact that it is a "how long is a piece of string" type of question - but any formula of reasonable accuracy or well experienced estimate is appreciated.

like image 417
user1210708 Avatar asked Mar 11 '23 15:03

user1210708


1 Answers

The JOOQ code generator adds a field per table/sequence/key in the code base. The code generator already assures that the code only sets this field but does not create any complex statement, which reduces the code size. As the field is static, this further reduces the required byte code. Each initialization instruction is a pair of a field read and a field write. In byte code, each such instruction is:

GETSTATIC (reference)
PUTSTATIC (reference)

A byte code is a single byte where each field reference is a two byte index making each instruction count 6 bytes. As a static initializer requires to end with an (implicit) return statement, this adds another byte to the method. With 64kB - 1B available bytes per method and 6 bytes per field, this tells us that the initializer can hold at most 10.922 such fields per class before crossing the limit, i.e., support at most (65536 - 1) / 6 = 10.922 tables, sequences or keys.

The constant pool can contain at most 65536 entries. The calculation of a limit is a bit more difficult as the constant pool does not contain duplicate values but reuses an existing entry. We do the calculation for the worst case where no names are used more then once.

Each field reference is a compound of a class reference and and a name-and-type reference. The class reference contains another reference to a string with the type's name. The name-and-type reference contains two references to the field name and the field descriptor as string. The set instruction's owner type is always duplicated, we assume that the get instruction is in a worst case never duplicated, accounting to 2 entries per instruction pair. The set and get fields' types and names are always equal for each instruction pair what accounts to two entries per instruction pair. The wrapping name-and-type entry is always unique for both sides, accounting to two entries per instruction pair. This leaves us with 2 + 1 + 1 + 2 = 6 entries per instruction pair. The set instruction's owner type will always be in the constant pool as it is required to define the class. Furthermore, we need to account for the basic information like the defined class's name and its default constructor. Fortunately, the annotations have source retention such that they are excluded from the class file. The general housekeeping requires 12 entries what leaves us with (65536 - 12) / 6 = 10.920 tables, sequences or keys.

We need to respect both limits, therefore 10.920 tables, sequences or keys is the number you are bound by.

Be aware that the actual number might be lower due to constant pool entries being defined for inner class attributes. This generates additional inner class references per inner class what reduces the amount of free entries. I guess you won't run into any troubles if you stay below 10.000 elements.

like image 130
Rafael Winterhalter Avatar answered Mar 14 '23 15:03

Rafael Winterhalter