JDK-8308023 - Exponential classfile blowup with nested try/finally

Archie Cobbs archie.cobbs at gmail.com
Thu Jul 27 18:33:41 UTC 2023


This issue caught my eye: JDK-8308023
<https://bugs.openjdk.org/browse/JDK-8308023> - Javac generates
exponentially large class file with nested try catch statements

In a nutshell, since JSR/RET is no longer allowed/used, we now compile try
{ X } finally { Y } into this:

    X
    Y
    goto L2
L1: Store exception in local e1
    Y
    Load exception from local e1
    Throw exception
L2: ...

The L1 label is the target for the exception range surrounding X.

Note that the finally block Y is duplicated.

This means that if we hare N nested finally's:

    try {
      X0
    } finally {
      try {
        X1
      } finally {
        try {
          X2
        } finally {
          .... try {
                XN
              } finally {
                // done
          ... }
          }
        }
      }
    }

then each block Xi will be replicated 2^i times in the classfile.

Question: Can we solve this problem simply by avoiding the duplication of
finally blocks?

What if we compiled try { X } finally { Y } into this:

    X
    Store null in local e1         // new instruction
    goto L2
L1: Store exception in local e1
L2: Y
    Load exception from local e1
    If null, goto L3               // new instruction
    Load exception from local e1   // new instruction
    Throw exception
L3: ...

There are three new instructions, so in trivial cases this would make the
classfile larger. But in the highly nested cases it would change the
classfile growth from exponential to linear.

Thoughts? What am I missing?

-Archie

-- 
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20230727/29ef3604/attachment.htm>


More information about the compiler-dev mailing list