The Case of the Missing Constant Structures

I ran into an interesting bug today when messing around with Beret, my WIP attempt at a Java decompiler. For some reason, it would fail to read certain class files, in which it would encounter an invalid constant pool entry and crash, unable to proceed. Upon further investigation I found that it was actually reading into the next structure of the class file (the access flags) in an attempt to parse them as constant structures, and would freak out when it didn't recognize the data. Without much effort I discovered it was inexplicably discovering two fewer structures in the table than indicated by the defined pool size.

So, I tweaked the code to subtract two from the expected size and commented out everything but the pool dump. Then I compared it to the javap dump and realized javap was printing out something like this:

Screenshot

At this point I'm asking myself, "What the hell happened to entry #95?" There was one other instance of this in the javap output, which almost certainly explained Beret coming up short. But, why was it being omitted?

I noted that the entry before the missing one was a double constant in both cases. Turns out, the Java class file format documentation includes this little gem:

All 8-byte constants take up two entries in the constant_pool table of the class file.

Aaaand there's our problem. Why this is in the specification, I have no idea, especially given the existence of UTF-8 structures which can and generally will be way longer than the standard 4 bytes. But, live and learn, I guess. Would have saved me 30 minutes of debugging time anyway.

Moral of the story: Don't be lazy when reading documentation.

Posted by Max Roncace on