/** * Correct invocations to a method that has been renamed. * If a method is renamed, calls to that method must be also * modified so that the method with the new name will be called. * * <p>The method must be declared in the same class before and * after it is renamed. * * <p>Note that the target object, the parameters, or * the type of invocation * (static method call, interface call, or private method call) * are not modified. Only the method name is changed. * * @param oldMethodName the old name of the method. * @param newMethod the method with the new name. * @see javassist.CtMethod#setName(String) */ public void redirectMethodCall(String oldMethodName, CtMethod newMethod) throws CannotCompileException { transformers = new TransformCall(transformers, oldMethodName, newMethod); }
/** * Modify a method body so that field read/write expressions access * a different field from the original one. * * <p>Note that this method changes only the filed name and the class * declaring the field; the type of the target object does not change. * Therefore, the substituted field must be declared in the same class * or a superclass of the original class. * * <p>Also, <code>clazz</code> and <code>newClass</code> must specify * the class directly declaring the field. They must not specify * a subclass of that class. * * @param field the originally accessed field. * @param newClass the class declaring the substituted field. * @param newFieldname the name of the substituted field. */ public void redirectFieldAccess(CtField field, CtClass newClass, String newFieldname) { transformers = new TransformFieldAccess(transformers, field, newClass.getName(), newFieldname); }
/** * Modify a method body so that instantiation of the class * specified by <code>oldClass</code> * is replaced with instantiation of another class <code>newClass</code>. * For example, * <code>replaceNew(ctPoint, ctPoint2)</code> * (where <code>ctPoint</code> and <code>ctPoint2</code> are * compile-time classes for class <code>Point</code> and class * <code>Point2</code>, respectively) * replaces all occurrences of: * * <pre>new Point(x, y)</pre> * * in the method body with: * * <pre>new Point2(x, y)</pre> * * <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>. * It must have the same set of methods, fields, and constructors as the * replaced class. */ public void replaceNew(CtClass oldClass, CtClass newClass) { transformers = new TransformNewClass(transformers, oldClass.getName(), newClass.getName()); }
protected int match(int c, int pos, CodeIterator iterator, int typedesc, ConstPool cp) throws BadBytecode { if (newIndex == 0) { String desc = Descriptor.ofParameters(parameterTypes) + 'V'; desc = Descriptor.insertParameter(classname, desc); int nt = cp.addNameAndTypeInfo(newMethodname, desc); int ci = cp.addClassInfo(newClassname); newIndex = cp.addMethodrefInfo(ci, nt); constPool = cp; } if (saveCode == null) makeCode(parameterTypes, cp); return match2(pos, iterator); }
/** * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL * so that a different method is invoked. The class name in the operand * of these instructions might be a subclass of the target class specified * by <code>classname</code>. This method transforms the instruction * in that case unless the subclass overrides the target method. */ public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode { int c = iterator.byteAt(pos); if (c == INVOKEINTERFACE || c == INVOKESPECIAL || c == INVOKESTATIC || c == INVOKEVIRTUAL) { int index = iterator.u16bitAt(pos + 1); String cname = cp.eqMember(methodname, methodDescriptor, index); if (cname != null && matchClass(cname, clazz.getClassPool())) { int ntinfo = cp.getMemberNameAndType(index); pos = match(c, pos, iterator, cp.getNameAndTypeDescriptor(ntinfo), cp); } } return pos; }
private void makeCode2(Bytecode save, Bytecode load, int i, int n, CtClass[] paramTypes, int var) { if (i < n) { int size = load.addLoad(var, paramTypes[i]); makeCode2(save, load, i + 1, n, paramTypes, var + size); save.addStore(var, paramTypes[i]); } else locals = var - maxLocals; } }
public void initialize(ConstPool cp, CodeAttribute attr) { super.initialize(cp, attr); locals = 0; maxLocals = attr.getMaxLocals(); saveCode = loadCode = null; }
public void initialize(ConstPool cp, CtClass clazz, MethodInfo minfo) throws CannotCompileException { initialize(cp, minfo.getCodeAttribute()); }
transformers = new TransformReadField(transformers, field, calledClass.getName(), calledMethod);
transformers = new TransformWriteField(transformers, field, calledClass.getName(), calledMethod);
transformers = new TransformNew(transformers, newClass.getName(), calledClass.getName(), calledMethod);
transformers = new TransformBefore(transformers, origMethod, beforeMethod);
static String isField(ClassPool pool, ConstPool cp, CtClass fclass, String fname, boolean is_private, int index) { if (!cp.getFieldrefName(index).equals(fname)) return null; try { CtClass c = pool.get(cp.getFieldrefClassName(index)); if (c == fclass || (!is_private && isFieldInSuper(c, fclass, fname))) return cp.getFieldrefType(index); } catch (NotFoundException e) {} return null; }
private String getTopType(int pos) throws BadBytecode { Frame frame = getFrame(pos); if (frame == null) return null; CtClass clazz = frame.peek().getCtClass(); return clazz != null ? Descriptor.toJvmName(clazz) : null; }
private void makeCode2(Bytecode save, Bytecode load, int i, int n, CtClass[] paramTypes, int var) { if (i < n) { int size = load.addLoad(var, paramTypes[i]); makeCode2(save, load, i + 1, n, paramTypes, var + size); save.addStore(var, paramTypes[i]); } else locals = var - maxLocals; } }
@Override public void initialize(ConstPool cp, CodeAttribute attr) { super.initialize(cp, attr); locals = 0; maxLocals = attr.getMaxLocals(); saveCode = loadCode = null; }
public void initialize(ConstPool cp, CtClass clazz, MethodInfo minfo) throws CannotCompileException { initialize(cp, minfo.getCodeAttribute()); }
/** * Correct invocations to a method that has been renamed. * If a method is renamed, calls to that method must be also * modified so that the method with the new name will be called. * * <p>The method must be declared in the same class before and * after it is renamed. * * <p>Note that the target object, the parameters, or * the type of invocation * (static method call, interface call, or private method call) * are not modified. Only the method name is changed. * * @param oldMethodName the old name of the method. * @param newMethod the method with the new name. * @see javassist.CtMethod#setName(String) */ public void redirectMethodCall(String oldMethodName, CtMethod newMethod) throws CannotCompileException { transformers = new TransformCall(transformers, oldMethodName, newMethod); }
protected void makeCode(CtClass[] paramTypes, ConstPool cp) { Bytecode save = new Bytecode(cp, 0, 0); Bytecode load = new Bytecode(cp, 0, 0); int var = maxLocals; int len = (paramTypes == null) ? 0 : paramTypes.length; load.addAload(var); makeCode2(save, load, 0, len, paramTypes, var + 1); save.addAstore(var); saveCode = save.get(); loadCode = load.get(); }
protected void makeCode(CtClass[] paramTypes, ConstPool cp) { Bytecode save = new Bytecode(cp, 0, 0); Bytecode load = new Bytecode(cp, 0, 0); int var = maxLocals; int len = (paramTypes == null) ? 0 : paramTypes.length; load.addAload(var); makeCode2(save, load, 0, len, paramTypes, var + 1); save.addAstore(var); saveCode = save.get(); loadCode = load.get(); }