/** * {@inheritDoc} * <p> * Here we add code to catch the unexpected exception that can occur during method execution and * notify our hooks about it. We are sending the raised exception as the result of the method * invocation. */ @Override public void visitMaxs(int maxStack, int maxLocals) { // the definition of the end of the try block Label tryBlockEnd = new Label(); visitLabel(tryBlockEnd); // setup for the finally block super.visitTryCatchBlock(tryBlockStart, tryBlockEnd, finallyHandler, null); visitLabel(finallyHandler); // generate code for calling after body // push exception on the stack and pass to after body call as the result dup(); generateAfterBodyCall(); // we can not substitute the result when exception is thrown just pop pop(); mv.visitInsn(ATHROW); // update the max stack stuff super.visitMaxs(maxStack, maxLocals); }
/** * {@inheritDoc} */ @Override protected void onMethodEnter() { // generate code for calling before body generateBeforeBodyCall(); if (substitutionDescriptor.isReturnValueSubstitution()) { // and code for returning if result is not null generateReturnIfResultNotNull(); } else { // pop to clear result on stack pop(); } if (substitutionDescriptor.isParameterValueSubstitution()) { // add code for substituting the parameter generateParameterSubstitutionIfResultNotNull(); } // start our try block visitLabel(tryBlockStart); }
visitLabel(continueExecution);
/** * Generates call for returning result on stack if needed. */ private void generateReturnIfResultNotNull() { // create new local and store result int local = newLocal(IInstrumenterConstant.OBJECT_TYPE); storeLocal(local); Label continueExecution = new Label(); // then load for null check loadLocal(local); ifNull(continueExecution); // we can only return result if return type is not Void if (!Type.VOID_TYPE.equals(returnType)) { // then load for instance of check if it's an object loadLocal(local); instanceOfSafe(returnType); // if zero compare // we compare the result of the instance of check with the 0 // so we will continue execution if the result is false (0) ifZCmp(EQ, continueExecution); // load again for return loadLocal(local); // we need to unbox here if needed as we are changing the result unbox(returnType); } // if method returned something, anyway return (also on void) returnValue(); visitLabel(continueExecution); }