/** * Checks a given class * * @param cr a <code>ClassReader</code> that contains bytecode for the analysis. * @param loader a <code>ClassLoader</code> which will be used to load referenced classes. This is * useful if you are verifiying multiple interdependent classes. * @param dump true if bytecode should be printed out not only when errors are found. * @param pw write where results going to be printed */ public static void verify( final ClassReader cr, final ClassLoader loader, final boolean dump, final PrintWriter pw) { ClassNode cn = new ClassNode(); cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG); Type syperType = cn.superName == null ? null : Type.getObjectType(cn.superName); List methods = cn.methods; List interfaces = new ArrayList(); for (Iterator i = cn.interfaces.iterator(); i.hasNext(); ) { interfaces.add(Type.getObjectType(i.next().toString())); } for (int i = 0; i < methods.size(); ++i) { MethodNode method = (MethodNode) methods.get(i); SimpleVerifier verifier = new SimpleVerifier(Type.getObjectType(cn.name), syperType, interfaces, false); Analyzer a = new Analyzer(verifier); if (loader != null) { verifier.setClassLoader(loader); } try { a.analyze(cn.name, method); if (!dump) { continue; } } catch (Exception e) { e.printStackTrace(pw); } printAnalyzerResult(method, a, pw); } pw.flush(); }
static void printAnalyzerResult(MethodNode method, Analyzer a, final PrintWriter pw) { Frame[] frames = a.getFrames(); TraceMethodVisitor mv = new TraceMethodVisitor(); pw.println(method.name + method.desc); for (int j = 0; j < method.instructions.size(); ++j) { method.instructions.get(j).accept(mv); StringBuffer s = new StringBuffer(); Frame f = frames[j]; if (f == null) { s.append('?'); } else { for (int k = 0; k < f.getLocals(); ++k) { s.append(getShortName(f.getLocal(k).toString())).append(' '); } s.append(" : "); for (int k = 0; k < f.getStackSize(); ++k) { s.append(getShortName(f.getStack(k).toString())).append(' '); } } while (s.length() < method.maxStack + method.maxLocals + 1) { s.append(' '); } pw.print(Integer.toString(j + 100000).substring(1)); pw.print(" " + s + " : " + mv.buf); // mv.text.get(j)); } for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv); pw.print(" " + mv.buf); } pw.println(); }