public static byte[] transform(byte[] bytes) { ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES); boolean changed = false; Iterator<MethodNode> it = cnode.methods.iterator(); while(it.hasNext()) { MethodNode mnode = it.next(); ReferenceDetector r = new ReferenceDetector(); mnode.accept(new RemappingMethodAdapter(mnode.access, mnode.desc, new MethodVisitor(Opcodes.ASM4) {}, r)); if(r.found) { it.remove(); changed = true; } } if(changed) bytes = ASMHelper.createBytes(cnode, 0); return bytes; }
public static byte[] transform(byte[] bytes) { ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES); boolean changed = false; Iterator<MethodNode> it = cnode.methods.iterator(); while (it.hasNext()) { MethodNode mnode = it.next(); ReferenceDetector r = new ReferenceDetector(); mnode.accept(new RemappingMethodAdapter(mnode.access, mnode.desc, new MethodVisitor(Opcodes.ASM4) { }, r)); if (r.found) { it.remove(); changed = true; } } if (changed) { bytes = ASMHelper.createBytes(cnode, 0); } return bytes; }
@Override public void visitEnd() { // add all the fields of the class we're going to merge. for (Iterator<?> it = classToMerge.fields.iterator(); it.hasNext();) { ((FieldNode) it.next()).accept(this); } // add all the methods that we to include. for (Iterator<?> it = classToMerge.methods.iterator(); it.hasNext();) { MethodNode mn = (MethodNode) it.next(); if (mn.name.equals("<init>")) { continue; } String[] exceptions = new String[mn.exceptions.size()]; mn.exceptions.toArray(exceptions); MethodVisitor mv = cv.visitMethod(mn.access | Modifier.FINAL, mn.name, mn.desc, mn.signature, exceptions); if (verifyBytecode) { mv = new CheckMethodVisitorFsm(api, mv); } mn.instructions.resetLabels(); // mn.accept(new RemappingMethodAdapter(mn.access, mn.desc, mv, new // SimpleRemapper("org.apache.drill.exec.compile.ExampleTemplate", "Bunky"))); ClassSet top = set; while (top.parent != null) { top = top.parent; } mn.accept(new RemappingMethodAdapter(mn.access, mn.desc, mv, new SimpleRemapper(top.precompiled.slash, top.generated.slash))); } super.visitEnd(); }
/** * Copy a method and rename it; everything else will be exactly the same * @return The renamed method copy */ public static MethodNode copyAndRenameMethod(ClassNode classNode, MethodNode method, String newMethodName) { MethodVisitor methodCopyVisitor = classNode.visitMethod(method.access, newMethodName, method.desc, method.signature, method.exceptions.toArray(new String[method.exceptions.size()])); method.accept(new RemappingMethodAdapter(method.access, method.desc, methodCopyVisitor, new Remapper(){})); return methodCopyVisitor instanceof MethodNode ? (MethodNode) methodCopyVisitor : null; }
/** * Adds the method to the base class * @param methodNode */ private void addMethod(MethodNode methodNode){ String[] exceptions = new String[methodNode.exceptions.size()]; methodNode.exceptions.toArray(exceptions); MethodVisitor mv = cv.visitMethod(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, exceptions); methodNode.instructions.resetLabels(); // SimpleRemapper -> maps old name to new name // updates owners and descriptions appropriately methodNode.accept(new RemappingMethodAdapter(methodNode.access, methodNode.desc, mv, new SimpleRemapper(classToMerge.name, baseClassName))); }
protected MethodVisitor createRemappingMethodAdapter( int access, String newDesc, MethodVisitor mv) { return new RemappingMethodAdapter(access, newDesc, mv, remapper) { @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { if (name.equals("<init>") && isObject && owner.equals("java/lang/Object")) { return; } super.visitMethodInsn(opcode, owner, stripMethodSuffix(name), desc, itf); } }; }
protected MethodVisitor createRemappingMethodAdapter(int access, String newDesc, MethodVisitor mv) { return new RemappingMethodAdapter(access, newDesc, mv, remapper) { @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { if (name.equals("<init>") && isObject && owner.equals("java/lang/Object")) { return; } super.visitMethodInsn(opcode, owner, stripMethodSuffix(name), desc, itf); } }; }
@Override public void visitEnd() { // add all the fields of the class we're going to merge. for (Iterator<?> it = classToMerge.fields.iterator(); it.hasNext();) { // Special handling for nested classes. Drill uses non-static nested // "inner" classes in some templates. Prior versions of Drill would // create the generated nested classes as static, then this line // would copy the "this$0" field to convert the static nested class // into a non-static inner class. However, that approach is not // compatible with plain-old Java compilation. Now, Drill generates // the nested classes as non-static inner classes. As a result, we // do not want to copy the hidden fields; we'll end up with two if // we do. FieldNode field = (FieldNode) it.next(); if (! field.name.startsWith("this$")) { field.accept(this); } } // add all the methods that we to include. for (Iterator<?> it = classToMerge.methods.iterator(); it.hasNext();) { MethodNode mn = (MethodNode) it.next(); if (mn.name.equals("<init>")) { continue; } String[] exceptions = new String[mn.exceptions.size()]; mn.exceptions.toArray(exceptions); MethodVisitor mv = cv.visitMethod(mn.access | Modifier.FINAL, mn.name, mn.desc, mn.signature, exceptions); if (verifyBytecode) { mv = new CheckMethodVisitorFsm(api, mv); } mn.instructions.resetLabels(); // mn.accept(new RemappingMethodAdapter(mn.access, mn.desc, mv, new // SimpleRemapper("org.apache.drill.exec.compile.ExampleTemplate", "Bunky"))); ClassSet top = set; while (top.parent != null) { top = top.parent; } mn.accept(new RemappingMethodAdapter(mn.access, mn.desc, mv, new SimpleRemapper(top.precompiled.slash, top.generated.slash))); } super.visitEnd(); }