Synergetic Stupidity in Java
January 21st, 2009In the Java “class” file format specification, the length of the bytecode of any method is limited to 64KB. This arbitrary limitation is bad in itself, but see below what it does in conjunction with the other stupider Java ‘feature’.
In any normal language, a literal array constant (used for array initialization) is represented as a compact block of data. For example when initializing an array with 1000 byte values, you’d expect the initialization data to take up 1KB (1000 x 1B). But not so in Java, not at all.
Let’s consider a long array of bytes, initialized with some data.
static final byte B[] = {10, 20, 30, 40, 50, 60, 70, 80, …};
In the “class” format there is no provision for storing the array initialization data in a compact format. Instead, bytecode instructions are generated for filling-in the array, a small block of bytecodes for each entry of the array data:
dup //1 byte; duplicate the array address on the stack sipush 300 //3 bytes; the array index where to store the value bipush 99 //2 bytes; the value to store bastore //1 byte; do the store
This adds up to 7 bytes for each entry of the array. So if you initialize an array of 5000 bytes, this would generate 35KB of bytecode instead of the 5KB that would normally be enough to store the data.
For an array of int, float or larger types, the bytecode structure is a bit different, in that the integer value is not inlined in the bytecode, but instead read from a constant pool.
dup //1 byte sipush 300 //3 bytes; the array index ldc_w 400 //3 bytes; load int from constant pool position iastore //1 byte
Let’s put in a small table the amount of data Java uses for initializing arrays of different types:
| Type | Bytes / entry | Stupidity boost |
| byte[] | 7 | 7 x |
| short[] | 8 | 4 x |
| int[], float[] | 8 + 4 | 3 x |
| long[] | 8 + 8 | 2 x |
This form of doing array initialization is in my opinion the stupidest miss of the “class” file format.
But lets see where Stupidity Synergy comes into play. Synergy means that sometimes, when you put together one stupid feature with another stupid feature, you get a result that is larger than the sum of the parts. Java achieves synergy by combining the 64KB method size limit with the peculiar way of compiling the array initialization.
As we’ve seen, bytecode (i.e. method code) is needed for any array initialization. Even initializing a static array at the class level produces an invisible method that contains the code for array initialization. Combining this with the method size limit produces very restrictive limits on the size of array initializations.
| Type | Array initialization size limit |
| byte | 9K |
| short | 8K |
| int, float | 8K |
Nice powerful language, where you get a “code too large” compilation error when you try to initialize a byte array with more than 9K entries…
