BadBytecode (jsr, ret instructions)

This page refers to the issue from ticket INSPECTIT-197 but could occur if Java 6 bytecode is used.

If you encounter an exception like the following, then please contact one of the inspectIT members immediately:

Caused by: info.novatec.inspectit.javassist.bytecode.BadBytecode: jsr at 210
        at info.novatec.inspectit.javassist.bytecode.stackmap.Tracer.throwBadBytecode(Tracer.java:144)
        at info.novatec.inspectit.javassist.bytecode.stackmap.Tracer.visitJSR(Tracer.java:133)
        at info.novatec.inspectit.javassist.bytecode.stackmap.Tracer.doOpcode148_201(Tracer.java:563)
        at info.novatec.inspectit.javassist.bytecode.stackmap.Tracer.doOpcode(Tracer.java:101)
        at info.novatec.inspectit.javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:182)
        at info.novatec.inspectit.javassist.bytecode.stackmap.MapMaker.traceException(MapMaker.java:213)
        at info.novatec.inspectit.javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:175)
        at info.novatec.inspectit.javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:192)
        at info.novatec.inspectit.javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:141)
        at info.novatec.inspectit.javassist.bytecode.stackmap.MapMaker.make(MapMaker.java:96)
        at info.novatec.inspectit.javassist.bytecode.MethodInfo.rebuildStackMap(MethodInfo.java:417)
        at info.novatec.inspectit.javassist.bytecode.MethodInfo.rebuildStackMapIf6(MethodInfo.java:399)
        at info.novatec.inspectit.javassist.CtBehavior.insertBefore(CtBehavior.java:719) 

The problem is often also seen in an exception as follows:

INFO: Could not add prepared statement, no sql available! Method ID(local): 59
27.08.2010 10:18:24 info.novatec.inspectit.agent.sensor.method.jdbc.PreparedStatementHook afterConstructor
INFO: This is not an inspectIT issue, please consult the management of inspectIT and send the following stacktrace!
java.util.NoSuchElementException

Background

This exception is thrown from within javassist with a reason: There is a new Java 6 bytecode verifier for Java 6 compiled classes which Javassist is trying to imitate. If Java 6 classes are generated (e.g. with javac) no 'jsr ' and 'ret ' instructions are used anymore. Please take a look at the following link which explains this: https://jdk.dev.java.net/verifier.html

"The new verifier does not allow instructions jsr and ret. These instructions are used to make subroutines for generating try/finally blocks. Instead the compiler will inline subroutine code which means the byte code in subroutines will be inserted in places where the subroutines are called. As a consequence, the compiler will sometimes generate more byte codes than with jsr/ret. Since the class file format limits the size of methods, some degenerated methods with excessively large or nested finally blocks might exhaust this limit and fail to compile."

   ...
   152: jsr     166
   155: areturn
   156: astore  11
   158: aconst_null
   159: jsr     166
   162: pop
   163: aload   11
   165: athrow
   166: astore  9
   168: dup
   169: astore  8
   171: getstatic       #158; //Field _WLDF$INST_FLD_JDBC_After_Statement_Internal:Lweblogic/diagnostics/instrumentation/DelegatingMonitor;
   174: invokeinterface #122,  1; //InterfaceMethod weblogic/diagnostics/instrumentation/DelegatingMonitor.isEnabled:()Z
   179: ifeq    203
   182: getstatic       #486; //Field _WLDF$INST_JPFLD_3:Lweblogic/diagnostics/instrumentation/JoinPoint;
   185: aconst_null
   186: aload   8
   188: invokestatic    #137; //Method weblogic/diagnostics/instrumentation/InstrumentationSupport.createDynamicJoinPoint:(Lweblogic/diagnostics/instrumentation/JoinPoint;[Ljava/lang/Object;Ljava/lang/Object;)Lweblogic/diagnostics/instrumentation/DynamicJoinPoint;
   191: getstatic       #158; //Field _WLDF$INST_FLD_JDBC_After_Statement_Internal:Lweblogic/diagnostics/instrumentation/DelegatingMonitor;
   194: dup
   195: invokeinterface #141,  1; //InterfaceMethod weblogic/diagnostics/instrumentation/DelegatingMonitor.getActions:()[Lweblogic/diagnostics/instrumentation/DiagnosticAction;
   200: invokestatic    #145; //Method weblogic/diagnostics/instrumentation/InstrumentationSupport.process:(Lweblogic/diagnostics/instrumentation/JoinPoint;Lweblogic/diagnostics/instrumentation/DiagnosticMonitor;[Lweblogic/diagnostics/instrumentation/DiagnosticAction;)V
   203: ret     9
   ...

Solution

Javassist will be changed so that no exceptions are thrown if those two instructions are encountered. But it is not totally clear if that works in 100% of the cases. During the instrumentation phase of the classes, please take a look at the console and watch out for logging statements like:

"Found 'jsr' at pos: ... . New Java 6 bytecode verifier cannot be used for this class..."

Again, please consult one of the inspectIT members to see if some other workaround can be used.