@RequiresNonNull("type") private void addMixin(ClassNode mixinClassNode) { List<FieldNode> fieldNodes = mixinClassNode.fields; for (FieldNode fieldNode : fieldNodes) { fieldNode.accept(this); } List<MethodNode> methodNodes = mixinClassNode.methods; for (MethodNode mn : methodNodes) { if (mn.name.equals("<init>")) { continue; } String[] exceptions = Iterables.toArray(mn.exceptions, String.class); MethodVisitor mv = cw.visitMethod(mn.access, mn.name, mn.desc, mn.signature, exceptions); mn.accept(new MethodRemapper(mv, new SimpleRemapper(mixinClassNode.name, type.getInternalName()))); } }
@Override protected void handleClazz(JarFile jarFile, JarOutputStream jos, JarEntry ze, String pathName) { // logger.log(pathName); if (reMapping.containsKey(pathName.substring(0, pathName.length() - 6))) { logger.info("[ClazzReplacer] remove class " + pathName + " form " + jarFile); return; } try { InputStream in = jarFile.getInputStream(ze); ClassReader cr = new ClassReader(in); ClassWriter cw = new ClassWriter(0); RemappingClassAdapter remappingClassAdapter = new RemappingClassAdapter(cw, new SimpleRemapper(reMapping)); cr.accept(remappingClassAdapter, ClassReader.EXPAND_FRAMES); InputStream inputStream = new ByteArrayInputStream(cw.toByteArray()); copyStreamToJar(inputStream, jos, pathName, ze.getTime()); } catch (Throwable e) { System.err.println("[ClazzReplacer] rewrite error > " + pathName); justCopy(jarFile, jos, ze, pathName); } }
public static void applyMappings(Map<String, ClassNode> classMap, Map<String, String> remap) { log.debug("Applying mappings ["); for (Map.Entry<String, String> entry : remap.entrySet()) { String k = entry.getKey(); String v = entry.getValue(); if (k.equals(v)) continue; // skip members with same name // field format = [ "<owner>.<name>" : "<newname>" ] // method format = [ "<owner>.<name> <desc>" : "<newname>" ] int n = k.indexOf('.'); if (n != -1 && v.length() >= n && v.substring(n).equals(k)) { continue; } log.debug(" Map {} to {}", entry.getKey(), entry.getValue()); } log.debug("]"); SimpleRemapper remapper = new SimpleRemapper(remap); for (ClassNode node : new ArrayList<>(classMap.values())) { ClassNode copy = new ClassNode(); ClassRemapper adapter = new ClassRemapper(copy, remapper); node.accept(adapter); classMap.put(node.name, copy); } }
public byte[] rename(byte[] b, Map mappings) throws ClassFormatError { logger.info("Trying to rename class (" + b.length + " bytes)"); try { SimpleRemapper m = new SimpleRemapper(mappings); ClassReader cr = new ClassReader(b); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES/* | ClassWriter.COMPUTE_MAXS*/); ClassVisitor cv = new RemappingClassAdapter(cw, m); cr.accept(cv, ClassReader.SKIP_DEBUG); return cw.toByteArray(); } catch (Exception e) { logger.error("Failed renaming class: " + e); } return null; }
@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(); }
/** * 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))); }
/** * Creates a class visitor which weaves all changes and additions on the fly. * * @param classVisitor The class visitor to which this entry is to be written to. * @param typeInitializer The type initializer to apply. * @param contextRegistry A context registry to register the lazily created implementation context to. * @param writerFlags The writer flags being used. * @param readerFlags The reader flags being used. * @return A class visitor which is capable of applying the changes. */ private ClassVisitor writeTo(ClassVisitor classVisitor, TypeInitializer typeInitializer, ContextRegistry contextRegistry, int writerFlags, int readerFlags) { classVisitor = new RedefinitionClassVisitor(classVisitor, typeInitializer, contextRegistry, writerFlags, readerFlags); return originalType.getName().equals(instrumentedType.getName()) ? classVisitor : new ClassRemapper(classVisitor, new SimpleRemapper(originalType.getInternalName(), instrumentedType.getInternalName())); }
@Override public ClassVisitor wrap(TypeDescription instrumentedType, ClassVisitor classVisitor, Implementation.Context implementationContext, TypePool typePool, FieldList<FieldDescription.InDefinedShape> fields, MethodList<?> methods, int writerFlags, int readerFlags) { return new ClassRemapper(classVisitor, new SimpleRemapper(oldName, newName)); }
@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(); }
public ClassMangler(ClassVisitor visitor, String origName, String mangledName, String target) { super(Opcodes.ASM4, new RemappingClassAdapter(visitor, new SimpleRemapper(origName, mangledName))); this.mangledName = mangledName; this.target = target; }