byte[] nullAdaptClass(final InputStream is, final String name) throws Exception { JavaClass jc = new ClassParser(is, name + ".class").parse(); ClassGen cg = new ClassGen(jc); String cName = cg.getClassName(); ConstantPoolGen cp = cg.getConstantPool(); Method[] ms = cg.getMethods(); for (int j = 0; j < ms.length; ++j) { MethodGen mg = new MethodGen(ms[j], cg.getClassName(), cp); boolean lv = ms[j].getLocalVariableTable() == null; boolean ln = ms[j].getLineNumberTable() == null; if (lv) { mg.removeLocalVariables(); } if (ln) { mg.removeLineNumbers(); } mg.stripAttributes(skipDebug); InstructionList il = mg.getInstructionList(); if (il != null) { InstructionHandle ih = il.getStart(); while (ih != null) { ih = ih.getNext(); } if (compute) { mg.setMaxStack(); mg.setMaxLocals(); } } cg.replaceMethod(ms[j], mg.getMethod()); } return cg.getJavaClass().getBytes(); }
private void createMethod(Element method) throws IllegalXMLVMException { il = new InstructionList(); instructionHandlerManager = new InstructionHandlerManager(il); String methodName = method.getAttributeValue("name"); Element signature = method.getChild("signature", nsXMLVM); Type retType = collectReturnType(signature); Type[] argTypes = collectArgumentTypes(signature); short accessFlags = getAccessFlags(method); if (methodName.equals( ".cctor")) // Same concept, different names in .net/JVM. Note we are doing init of statics // for a class { System.out.println("Changed name to clinit"); methodName = "<clinit>"; accessFlags = 0x8; // static } MethodGen m = new MethodGen( accessFlags, retType, argTypes, null, methodName, fullQualifiedClassName, il, _cp); Element code = method.getChild("code", nsXMLVM); createCode(code); instructionHandlerManager.checkConsistency(); m.setMaxLocals(); m.setMaxStack(); _cg.addMethod(m.getMethod()); il.dispose(); }
/** * Convenience method. * * <p>Add an empty constructor to this class that does nothing but calling super(). * * @param access rights for constructor */ public void addEmptyConstructor(int access_flags) { InstructionList il = new InstructionList(); il.append(InstructionConstants.THIS); // Push `this' il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "<init>", "()V"))); il.append(InstructionConstants.RETURN); MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>", class_name, il, cp); mg.setMaxStack(1); addMethod(mg.getMethod()); }
byte[] counterAdaptClass(final InputStream is, final String name) throws Exception { JavaClass jc = new ClassParser(is, name + ".class").parse(); ClassGen cg = new ClassGen(jc); String cName = cg.getClassName(); ConstantPoolGen cp = cg.getConstantPool(); if (!cg.isInterface()) { FieldGen fg = new FieldGen(ACC_PUBLIC, Type.getType("I"), "_counter", cp); cg.addField(fg.getField()); } Method[] ms = cg.getMethods(); for (int j = 0; j < ms.length; ++j) { MethodGen mg = new MethodGen(ms[j], cg.getClassName(), cp); if (!mg.getName().equals("<init>") && !mg.isStatic() && !mg.isAbstract() && !mg.isNative()) { if (mg.getInstructionList() != null) { InstructionList il = new InstructionList(); il.append(new ALOAD(0)); il.append(new ALOAD(0)); il.append(new GETFIELD(cp.addFieldref(name, "_counter", "I"))); il.append(new ICONST(1)); il.append(new IADD()); il.append(new PUTFIELD(cp.addFieldref(name, "_counter", "I"))); mg.getInstructionList().insert(il); mg.setMaxStack(Math.max(mg.getMaxStack(), 2)); boolean lv = ms[j].getLocalVariableTable() == null; boolean ln = ms[j].getLineNumberTable() == null; if (lv) { mg.removeLocalVariables(); } if (ln) { mg.removeLineNumbers(); } cg.replaceMethod(ms[j], mg.getMethod()); } } } return cg.getJavaClass().getBytes(); }
/** * Processes each method in cg replacing any specified calls with static user calls. * * @param fullClassName must be packageName.className */ private boolean map_calls(ClassGen cg, String fullClassName, ClassLoader loader) { boolean transformed = false; try { pgen = cg.getConstantPool(); // Loop through each method in the class Method[] methods = cg.getMethods(); for (int i = 0; i < methods.length; i++) { MethodGen mg = new MethodGen(methods[i], cg.getClassName(), pgen); // Get the instruction list and skip methods with no instructions InstructionList il = mg.getInstructionList(); if (il == null) continue; if (debug) out.format("Original code: %s%n", mg.getMethod().getCode()); instrument_method(methods[i], mg); // Remove the Local variable type table attribute (if any). // Evidently, some changes we make require this to be updated, but // without BCEL support, that would be hard to do. Just delete it // for now (since it is optional, and we are unlikely to be used by // a debugger) for (Attribute a : mg.getCodeAttributes()) { if (is_local_variable_type_table(a)) { mg.removeCodeAttribute(a); } } // Update the instruction list mg.setInstructionList(il); mg.update(); // Update the max stack and Max Locals mg.setMaxLocals(); mg.setMaxStack(); mg.update(); // Update the method in the class cg.replaceMethod(methods[i], mg.getMethod()); if (debug) out.format("Modified code: %s%n", mg.getMethod().getCode()); // verify the new method // StackVer stackver = new StackVer(); // VerificationResult vr = stackver.do_stack_ver (mg); // log ("vr for method %s = %s%n", mg.getName(), vr); // if (vr.getStatus() != VerificationResult.VERIFIED_OK) { // System.out.printf ("Warning BCEL Verify failed for method %s: %s", // mg.getName(), vr); // System.out.printf ("Code: %n%s%n", mg.getMethod().getCode()); // System.exit(1); // } } cg.update(); } catch (Exception e) { out.format("Unexpected exception encountered: " + e); e.printStackTrace(); } return transformed; }