/**
   * Empties the method of all code (except for a return). This includes line numbers, exceptions,
   * local variables, etc.
   */
  public static void empty_method(MethodGen mg) {

    mg.setInstructionList(new InstructionList(new RETURN()));
    mg.removeExceptionHandlers();
    mg.removeLineNumbers();
    mg.removeLocalVariables();
    mg.setMaxLocals();
  }
Пример #2
0
  private static void addTimer(ClassGen cgen, Method method) {

    // set up the construction tools
    InstructionFactory ifact = new InstructionFactory(cgen);
    InstructionList ilist = new InstructionList();
    ConstantPoolGen pgen = cgen.getConstantPool();
    String cname = cgen.getClassName();
    MethodGen wrapgen = new MethodGen(method, cname, pgen);
    wrapgen.setInstructionList(ilist);

    // rename a copy of the original method
    MethodGen methgen = new MethodGen(method, cname, pgen);
    cgen.removeMethod(method);
    String iname = methgen.getName() + "_timing";
    methgen.setName(iname);
    cgen.addMethod(methgen.getMethod());
    Type result = methgen.getReturnType();

    // compute the size of the calling parameters
    Type[] parameters = methgen.getArgumentTypes();
    int stackIndex = methgen.isStatic() ? 0 : 1;
    for (int i = 0; i < parameters.length; i++) {
      stackIndex += parameters[i].getSize();
    }

    // save time prior to invocation
    ilist.append(
        ifact.createInvoke(
            "java.lang.System",
            "currentTimeMillis",
            Type.LONG,
            Type.NO_ARGS,
            Constants.INVOKESTATIC));
    ilist.append(InstructionFactory.createStore(Type.LONG, stackIndex));

    // call the wrapped method
    int offset = 0;
    short invoke = Constants.INVOKESTATIC;
    if (!methgen.isStatic()) {
      ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0));
      offset = 1;
      invoke = Constants.INVOKEVIRTUAL;
    }
    for (int i = 0; i < parameters.length; i++) {
      Type type = parameters[i];
      ilist.append(InstructionFactory.createLoad(type, offset));
      offset += type.getSize();
    }
    ilist.append(ifact.createInvoke(cname, iname, result, parameters, invoke));

    // store result for return later
    if (result != Type.VOID) {
      ilist.append(InstructionFactory.createStore(result, stackIndex + 2));
    }

    // print time required for method call
    ilist.append(
        ifact.createFieldAccess(
            "java.lang.System", "out", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
    ilist.append(InstructionConstants.DUP);
    ilist.append(InstructionConstants.DUP);
    String text = "Call to method " + methgen.getName() + " took ";
    ilist.append(new PUSH(pgen, text));
    ilist.append(
        ifact.createInvoke(
            "java.io.PrintStream",
            "print",
            Type.VOID,
            new Type[] {Type.STRING},
            Constants.INVOKEVIRTUAL));
    ilist.append(
        ifact.createInvoke(
            "java.lang.System",
            "currentTimeMillis",
            Type.LONG,
            Type.NO_ARGS,
            Constants.INVOKESTATIC));
    ilist.append(InstructionFactory.createLoad(Type.LONG, stackIndex));
    ilist.append(InstructionConstants.LSUB);
    ilist.append(
        ifact.createInvoke(
            "java.io.PrintStream",
            "print",
            Type.VOID,
            new Type[] {Type.LONG},
            Constants.INVOKEVIRTUAL));
    ilist.append(new PUSH(pgen, " ms."));
    ilist.append(
        ifact.createInvoke(
            "java.io.PrintStream",
            "println",
            Type.VOID,
            new Type[] {Type.STRING},
            Constants.INVOKEVIRTUAL));

    // return result from wrapped method call
    if (result != Type.VOID) {
      ilist.append(InstructionFactory.createLoad(result, stackIndex + 2));
    }
    ilist.append(InstructionFactory.createReturn(result));

    // finalize the constructed method
    wrapgen.stripAttributes(true);
    wrapgen.setMaxStack();
    wrapgen.setMaxLocals();
    cgen.addMethod(wrapgen.getMethod());
    ilist.dispose();
  }
Пример #3
0
  /**
   * 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;
  }