/** Loads the code of the method. */ protected Instruction[] loadCode(Method m) { Code c = m.getCode(); if (c == null) { return null; } InstructionList il = new InstructionList(c.getCode()); InstructionHandle[] hs = il.getInstructionHandles(); int length = hs.length; Instruction[] is = new Instruction[length]; for (int i = 0; i < length; i++) { is[i] = insnFactory.createAndInitialize(this, hs[i], i, m.getConstantPool()); if (c.getLineNumberTable() != null) { // annoying bug when BCEL don't seem to find linenumber - pos match // also sometimes linenumber tables are not available is[i].setContext( ci.getName(), name, c.getLineNumberTable().getSourceLine(is[i].getPosition()), is[i].getPosition()); } } return is; }
/** Returns the exceptions of the method. */ protected ExceptionHandler[] loadExceptions(Method m) { Code c = m.getCode(); if (c == null) { return null; } CodeException[] ce = c.getExceptionTable(); if (ce.length == 0) { return null; } int length = ce.length; ExceptionHandler[] eh = new ExceptionHandler[length]; ConstantPool cp = m.getConstantPool(); for (int i = 0; i < length; i++) { int ct = ce[i].getCatchType(); eh[i] = new ExceptionHandler( ((ct == 0) ? null : cp.getConstantString(ct, Constants.CONSTANT_Class).replace('/', '.')), ce[i].getStartPC(), ce[i].getEndPC(), ce[i].getHandlerPC()); } return eh; }
/** Loads the line numbers for the method. */ protected int[] loadLineNumbers(Method m) { Code c = m.getCode(); if (c == null) { return null; } LineNumberTable lnt = c.getLineNumberTable(); int length = code.length; int[] ln = new int[length]; if (lnt == null) { // no line information return null; } else { for (int i = 0; i < length; i++) { try { // annoying bug when BCEL don't seem to find linenumber - pos match ln[i] = lnt.getSourceLine(code[i].getPosition()); } catch (RuntimeException e) { System.out.print("^"); } } } return ln; }
@Override public void visit(Code obj) { sawSuperFinalize = false; super.visit(obj); bugAccumulator.reportAccumulatedBugs(); if (!getMethodName().equals("finalize") || !getMethodSig().equals("()V")) return; String overridesFinalizeIn = Lookup.findSuperImplementor(getDottedClassName(), "finalize", "()V", bugReporter); boolean superHasNoFinalizer = overridesFinalizeIn.equals("java.lang.Object"); // System.out.println("superclass: " + superclassName); if (obj.getCode().length == 1) { if (superHasNoFinalizer) { if (!getMethod().isFinal()) bugReporter.reportBug( new BugInstance(this, "FI_EMPTY", NORMAL_PRIORITY).addClassAndMethod(this)); } else bugReporter.reportBug( new BugInstance(this, "FI_NULLIFY_SUPER", NORMAL_PRIORITY) .addClassAndMethod(this) .addClass(overridesFinalizeIn)); } else if (obj.getCode().length == 5 && sawSuperFinalize) bugReporter.reportBug( new BugInstance(this, "FI_USELESS", NORMAL_PRIORITY).addClassAndMethod(this)); else if (!sawSuperFinalize && !superHasNoFinalizer) bugReporter.reportBug( new BugInstance(this, "FI_MISSING_SUPER_CALL", NORMAL_PRIORITY) .addClassAndMethod(this) .addClass(overridesFinalizeIn)); }
/** * overrides the visitor to find abstract methods that override concrete ones * * @param obj the context object of the currently parsed method */ @Override public void visitMethod(Method obj) { if (!obj.isAbstract()) return; String methodName = obj.getName(); String methodSig = obj.getSignature(); outer: for (JavaClass cls : superClasses) { Method[] methods = cls.getMethods(); for (Method m : methods) { if (m.isPrivate() || m.isAbstract()) continue; if (methodName.equals(m.getName()) && methodSig.equals(m.getSignature())) { BugInstance bug = new BugInstance(this, BugType.AOM_ABSTRACT_OVERRIDDEN_METHOD.name(), NORMAL_PRIORITY) .addClass(this) .addMethod(this); Code code = obj.getCode(); if (code != null) bug.addSourceLineRange(clsContext, this, 0, code.getLength() - 1); bugReporter.reportBug(bug); break outer; } } } }
public static int getMaxStack(Method m) { Code c = m.getCode(); if (c == null) { return 0; } return c.getMaxStack(); }
@Override public void visitCode(Code obj) { Method m = getMethod(); if (m.getReturnType() == Type.VOID) { return; } stack.resetForMethodEntry(this); ifBlocks.clear(); activeUnconditional = null; CodeException[] ces = obj.getExceptionTable(); if (CollectionUtils.isEmpty(ces)) { catchPCs = null; } else { catchPCs = new BitSet(); for (CodeException ce : ces) { catchPCs.set(ce.getHandlerPC()); } } gotoBranchPCs.clear(); casePositions.clear(); lookingForResetOp = false; try { super.visitCode(obj); } catch (StopOpcodeParsingException e) { // reported an issue, so get out } }
/** * Dumps the contents of the specified class to the specified directory. The file is named * dump_dir/[class].bcel. It contains a synopsis of the fields and methods followed by the jvm * code for each method. * * @param jc javaclass to dump * @param dump_dir directory in which to write the file */ public static void dump(JavaClass jc, File dump_dir) { try { dump_dir.mkdir(); File path = new File(dump_dir, jc.getClassName() + ".bcel"); PrintStream p = new PrintStream(path); // Print the class, super class and interfaces p.printf("class %s extends %s\n", jc.getClassName(), jc.getSuperclassName()); String[] inames = jc.getInterfaceNames(); if ((inames != null) && (inames.length > 0)) { p.printf(" "); for (String iname : inames) p.printf("implements %s ", iname); p.printf("\n"); } // Print each field p.printf("\nFields\n"); for (Field f : jc.getFields()) p.printf(" %s\n", f); // Print the signature of each method p.printf("\nMethods\n"); for (Method m : jc.getMethods()) p.printf(" %s\n", m); // If this is not an interface, print the code for each method if (!jc.isInterface()) { for (Method m : jc.getMethods()) { p.printf("\nMethod %s\n", m); Code code = m.getCode(); if (code != null) p.printf(" %s\n", code.toString().replace("\n", "\n ")); } } // Print the details of the constant pool. p.printf("Constant Pool:\n"); ConstantPool cp = jc.getConstantPool(); Constant[] constants = cp.getConstantPool(); for (int ii = 0; ii < constants.length; ii++) { p.printf(" %d %s\n", ii, constants[ii]); } p.close(); } catch (Exception e) { throw new Error("Unexpected error dumping javaclass", e); } }
/** * Loads the names of the local variables. * * <p>NOTE: BCEL only gives us a list of all *named* locals, which might not include all local * vars (temporaries, like StringBuilder). Note that we have to fill this with "?" in order to * make the returned array correspond with slot numbers */ protected String[] loadLocalVariableNames(Method m) { Code c = m.getCode(); if (c == null) { return null; } LocalVariableTable lvt = c.getLocalVariableTable(); if (lvt == null) { if (!warnedLocalInfo && !ci.isSystemClass()) { Debug.println(Debug.WARNING); Debug.println(Debug.WARNING, "No local variable information available"); Debug.println(Debug.WARNING, "for " + getCompleteName()); Debug.println(Debug.WARNING, "Recompile with -g to include this information"); Debug.println(Debug.WARNING); warnedLocalInfo = true; } return null; } LocalVariable[] lv = lvt.getLocalVariableTable(); int length = lv.length; String[] v = new String[c.getMaxLocals()]; for (int i = 0; i < length; i++) { v[lv[i].getIndex()] = lv[i].getName(); } for (int i = 0; i < v.length; i++) { if (v[i] == null) { v[i] = "?"; } } return v; }
@Override public void visit(Code obj) { if (!directChildOfTestCase && (getMethodName().equals("setUp") || getMethodName().equals("tearDown")) && !getMethod().isPrivate() && getMethodSig().equals("()V")) { sawSuperCall = false; super.visit(obj); if (sawSuperCall) { return; } JavaClass we = Lookup.findSuperImplementor(getThisClass(), getMethodName(), "()V", bugReporter); if (we != null && !we.getClassName().equals("junit.framework.TestCase")) { // OK, got a bug int offset = 0; if (getMethodName().equals("tearDown")) { offset = obj.getCode().length - 1; } Method superMethod = Lookup.findImplementation(we, getMethodName(), "()V"); Code superCode = superMethod.getCode(); if (superCode != null && superCode.getCode().length > 3) { bugReporter.reportBug( new BugInstance( this, getMethodName().equals("setUp") ? "IJU_SETUP_NO_SUPER" : "IJU_TEARDOWN_NO_SUPER", NORMAL_PRIORITY) .addClassAndMethod(this) .addMethod(we, superMethod) .describe(MethodAnnotation.METHOD_OVERRIDDEN) .addSourceLine(this, offset)); } } } }