@Override public void visitInsn(int opcode) { if ((newInvokeReplacer != null) && (opcode == DUP)) { return; // skip dup after new } super.visitInsn(opcode); }
@Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { // [*] // Fix all Foo.<field> to FooClone.<field> if (owner.equals(wd.superReference)) { owner = wd.thisReference; } super.visitFieldInsn(opcode, owner, name, desc); }
@Override public void visitTypeInsn(int opcode, String type) { if (opcode == NEW) { InvokeInfo invokeInfo = new InvokeInfo(type, INIT, StringPool.EMPTY); for (InvokeAspect aspect : aspects) { InvokeReplacer ir = aspect.pointcut(invokeInfo); if (ir != null) { newInvokeReplacer = ir; // new pointcut found, skip the new instruction and the following dup. // and then go to the invokespecial return; } } } super.visitTypeInsn(opcode, type); }
/** Invoked on INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE or INVOKEDYNAMIC. */ @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { // replace NEW.<init> if ((newInvokeReplacer != null) && (opcode == INVOKESPECIAL)) { String exOwner = owner; owner = newInvokeReplacer.getOwner(); name = newInvokeReplacer.getMethodName(); desc = changeReturnType(desc, 'L' + exOwner + ';'); super.visitMethodInsn(INVOKESTATIC, owner, name, desc); newInvokeReplacer = null; return; } InvokeInfo invokeInfo = new InvokeInfo(owner, name, desc); // [*] // creating FooClone.<init>; inside the FOO constructor // replace the very first invokespecial <init> call (SUB.<init>) // to targets subclass with target (FOO.<init>). if (methodInfo.getMethodName().equals(INIT)) { if ((firstSuperCtorInitCalled == false) && (opcode == INVOKESPECIAL) && name.equals(INIT) && owner.equals(wd.nextSupername)) { firstSuperCtorInitCalled = true; owner = wd.superReference; super.visitMethodInsn(opcode, owner, name, desc); return; } } // detection of super calls if ((opcode == INVOKESPECIAL) && (owner.equals(wd.nextSupername) && (name.equals(INIT) == false))) { throw new ProxettaException( "Super call detected in class " + methodInfo.getClassname() + " method: " + methodInfo.getSignature() + "\nProxetta can't handle super calls due to VM limitations."); } InvokeReplacer ir = null; // find first matching aspect for (InvokeAspect aspect : aspects) { ir = aspect.pointcut(invokeInfo); if (ir != null) { break; } } if (ir == null) { super.visitMethodInsn(opcode, owner, name, desc); return; } wd.proxyApplied = true; String exOwner = owner; owner = ir.getOwner(); name = ir.getMethodName(); switch (opcode) { case INVOKEINTERFACE: desc = prependArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_OBJECT); break; case INVOKEVIRTUAL: desc = prependArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_OBJECT); break; case INVOKESTATIC: break; default: throw new ProxettaException("Unsupported opcode: " + opcode); } // additional arguments if (ir.isPassOwnerName()) { desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_STRING); super.visitLdcInsn(exOwner); } if (ir.isPassMethodName()) { desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_STRING); super.visitLdcInsn(methodInfo.getMethodName()); } if (ir.isPassMethodSignature()) { desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_STRING); super.visitLdcInsn(methodInfo.getSignature()); } if (ir.isPassTargetClass()) { desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_CLASS); super.mv.visitLdcInsn(Type.getType('L' + wd.superReference + ';')); } if (ir.isPassThis()) { desc = appendArgument(desc, AsmUtil.L_SIGNATURE_JAVA_LANG_OBJECT); super.mv.visitVarInsn(ALOAD, 0); } super.visitMethodInsn(INVOKESTATIC, owner, name, desc); }