Skip to content

Coding errors

Brian S. O'Neill edited this page Aug 20, 2021 · 15 revisions

It's possible to make classes which the virtual machine rejects, resulting in a LinkageError of some kind:

  • BootstrapMethodError — caused by an indy/condy bootstrap method which fails to produce a valid result
  • ExceptionInInitializerError — caused by an exception throwing out from a static initializer
  • IncompatibleClassChangeError — caused by failing to implement an abstract method, or by trying to access an inaccessible class member
  • VerifyError — the code in a method body is broken

With the MethodMaker it's almost impossible to define code which can throw a VerifyError. One notable exception is when attempting to access a variable which hasn't been assigned yet:

    ClassMaker cm = ClassMaker.begin();
    MethodMaker mm = cm.addMethod(int.class, "test").public_().static_();
    var v1 = mm.var(int.class);
    mm.return_(v1); // v1 hasn't been assigned yet!
    var clazz = cm.finish();
    clazz.getMethod("test").invoke(null);

When running the above example:

Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    org/cojen/maker/ClassMaker-8.test()I @0: iload_0
  Reason:
    Type top (current frame, locals[0]) is not assignable to integer
  Current Frame:
    bci: @0
    flags: { }
    locals: { }
    stack: { }
  Bytecode:
    0000000: 1aac

The VerifyError tends to produce a ton of extra information, and this makes it look much scarier than it actually is. Try to find an execution path in the code which accesses a local variable that hasn't been definitely assigned.

Java compilers perform definite assignment analysis, and so a VerifyError isn't possible unless the compiler is defective. Although Cojen could perform definite assignment analysis too, it's redundant and adds overhead when making classes at runtime. A front end compiler which uses Cojen should perform it's own definite assignment analysis or prevent assignment problems in the first place.

Another type of VerifyError can be caused by a constructor which doesn't call a super or this method. If the constructor has no parameters and has no method body, the MethodMaker automatically calls the super constructor.

Clone this wiki locally