@Override
public void visit(Code obj) {
CodeException[] exp = obj.getExceptionTable();
LineNumberTable lineNumbers = obj.getLineNumberTable();
if (exp == null) {
return;
}
byte[] code = obj.getCode();
for (CodeException aExp : exp) {
int handled = aExp.getHandlerPC();
int start = aExp.getStartPC();
int end = aExp.getEndPC();
int cause = aExp.getCatchType();
boolean exitInTryBlock = false;
if (DEBUG) {
System.out.println("start = " + start + ", end = " + end + ", codeLength = " + code.length + ", handled = "
+ handled);
}
for (int j = start; j <= end && j < code.length;) {
int opcode = asUnsignedByte(code[j]);
if (NO_OF_OPERANDS[opcode] < 0) {
exitInTryBlock = true;
break;
}
j += 1 + NO_OF_OPERANDS[opcode];
if (opcode >= IRETURN && opcode <= RETURN || opcode >= IFEQ && opcode <= GOTO && (opcode != GOTO || j < end)) {
exitInTryBlock = true;
if (DEBUG) {
System.out.println("\texit: " + opcode + " in " + getFullyQualifiedMethodName());
}
break;
}
}
if (exitInTryBlock) {
if (DEBUG) {
System.out.println("Exit in try block");
}
continue;
}
if (handled < 5) {
continue;
}
@DottedClassName String causeName;
if (cause == 0) {
causeName = "java.lang.Throwable";
} else {
causeName = Utility.compactClassName(getConstantPool().getConstantString(cause, CONSTANT_Class), false);
if (!isChecked(causeName)) {
continue;
}
}
int jumpAtEnd = 0;
if (end < code.length && asUnsignedByte(code[end]) == GOTO) {
jumpAtEnd = getUnsignedShort(code, end + 1);
if (jumpAtEnd < handled) {
jumpAtEnd = 0;
}
}
int opcode = asUnsignedByte(code[handled]);
int afterHandler = 0;
if (DEBUG) {
System.out.println("DE:\topcode is " + OPCODE_NAMES[opcode] + ", " + asUnsignedByte(code[handled + 1]));
}
boolean drops = false;
boolean startsWithASTORE03 = opcode >= ASTORE_0 && opcode <= ASTORE_3;
if (startsWithASTORE03 && asUnsignedByte(code[handled + 1]) == RETURN) {
if (DEBUG) {
System.out.println("Drop 1");
}
drops = true;
afterHandler = handled + 1;
}
if (handled + 2 < code.length && opcode == ASTORE && asUnsignedByte(code[handled + 2]) == RETURN) {
drops = true;
afterHandler = handled + 2;
if (DEBUG) {
System.out.println("Drop 2");
}
}
if (handled + 3 < code.length && !exitInTryBlock) {
if (DEBUG) {
System.out.println("DE: checking for jumps");
}
if (startsWithASTORE03 && asUnsignedByte(code[handled - 3]) == GOTO) {
int offsetBefore = getUnsignedShort(code, handled - 2);
if (DEBUG) {
System.out.println("offset before = " + offsetBefore);
}
if (offsetBefore == 4) {
drops = true;
afterHandler = handled + 1;
if (DEBUG) {
System.out.println("Drop 3");
}
}
}
if (opcode == ASTORE && asUnsignedByte(code[handled - 3]) == GOTO) {
int offsetBefore = getUnsignedShort(code, handled - 2);
if (offsetBefore == 5) {
drops = true;
afterHandler = handled + 2;
if (DEBUG) {
System.out.println("Drop 4");
}
}
}
if (startsWithASTORE03 && asUnsignedByte(code[handled + 1]) == GOTO && asUnsignedByte(code[handled - 3]) == GOTO) {
int offsetBefore = getUnsignedShort(code, handled - 2);
int offsetAfter = getUnsignedShort(code, handled + 2);
if (offsetAfter > 0 && offsetAfter + 4 == offsetBefore) {
drops = true;
afterHandler = handled + 4;
if (DEBUG) {
System.out.println("Drop 5");
}
}
}
if (opcode == ASTORE && asUnsignedByte(code[handled + 2]) == GOTO && asUnsignedByte(code[handled - 3]) == GOTO) {
int offsetBefore = getUnsignedShort(code, handled - 2);
int offsetAfter = getUnsignedShort(code, handled + 3);
if (offsetAfter > 0 && offsetAfter + 5 == offsetBefore) {
drops = true;
afterHandler = handled + 5;
if (DEBUG) {
System.out.println("Drop 6");
}
}
}
}
boolean multiLineHandler = false;
if (DEBUG) {
System.out.println("afterHandler = " + afterHandler + ", handled = " + handled);
}
if (afterHandler > handled && lineNumbers != null) {
int startHandlerLinenumber = lineNumbers.getSourceLine(handled);
int endHandlerLinenumber = getNextExecutableLineNumber(lineNumbers, afterHandler) - 1;
if (DEBUG) {
System.out.println("Handler in lines " + startHandlerLinenumber + "-" + endHandlerLinenumber);
}