ClassFormatError: Illegal exception table range when generating class
In the middle of doing a complex transformation of a class, I actually end up
with no code between two labels, which are used in a TryCatchBlock (so the
block goes unused).
The ClassWriter correctly detects the TryCatchBlock is empty and replaces with
the NOP/ATHROW stuff, but it does not remove the entry from the exception
table, resulting in an error when the class is loaded by Java.
The following example demonstrates this:
import java.io.*;
import org.objectweb.asm.*;
public class AsmTryCatchBlockTestcase implements Opcodes {
public static void main(String[] args) throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_6, ACC_PUBLIC, "TryCatchIssue", null, "java/lang/Object", null);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC|ACC_STATIC, "m", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitInsn(RETURN);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitInsn(RETURN);
mv.visitTryCatchBlock(l0, l1, l2, null);
mv.visitMaxs(0, 0);
mv.visitEnd();
cw.visitEnd();
FileOutputStream fos = new FileOutputStream("TryCatchIssue.class");
fos.write(cw.toByteArray());
fos.close();
}
}
java TryCatchIssue then results in
$ java TryCatchIssue
Exception in thread "main" java.lang.ClassFormatError: Illegal exception table
range in class file TryCatchIssue
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: TryCatchIssue. Program will exit.
I do know that I can fix this (and indeed I do it) in my code by re-processing
the class to fix the exception table, but I believe that this would more
correctly be done inside ClassWriter, when the block is detected to be
unreachable code.
Thanks.