List of usage examples for org.objectweb.asm.tree ClassNode accept
public void accept(final ClassVisitor classVisitor)
From source file:org.qkit.core.asm.adapters.ChangeSuperclassAdapter.java
License:Open Source License
@Override public void visitEnd() { ClassNode cn = (ClassNode) cv; for (MethodNode mn : cn.methods) { InsnList il = mn.instructions;//from www. j a v a 2s . c o m Iterator<AbstractInsnNode> it = il.iterator(); while (it.hasNext()) { AbstractInsnNode ain = it.next(); if (ain instanceof MethodInsnNode) { MethodInsnNode m = (MethodInsnNode) ain; if ((m.getOpcode() == INVOKESPECIAL)) { MethodInsnNode min = (MethodInsnNode) ain; if (min.owner.equals(cn.superName)) { min.owner = superClass; } break; } } } } cn.superName = superClass; System.out.println(" [~S] " + cn.name + " extends " + cn.superName); cn.accept(next); }
From source file:org.spongepowered.asm.mixin.transformer.MixinTransformer.java
License:MIT License
/** * Apply mixins for specified target class to the class described by the * supplied byte array./*from w w w.jav a2 s . c o m*/ * * @param transformedName * @param basicClass * @param mixins * @return class bytecode after application of mixins */ private byte[] applyMixins(String transformedName, byte[] basicClass, SortedSet<MixinInfo> mixins) { // Tree for target class ClassNode targetClass = this.readClass(basicClass, true); for (MixinInfo mixin : mixins) { this.logger.log(mixin.getLoggingLevel(), "Mixing {} into {}", mixin.getName(), transformedName); this.applyMixin(transformedName, targetClass, mixin.createContextForTarget(targetClass)); } // Extension point this.postTransform(transformedName, targetClass, mixins); // Run CheckClassAdapter on the mixin bytecode if debug option is enabled if (MixinTransformer.DEBUG_VERIFY) { targetClass.accept(new CheckClassAdapter(new ClassWriter(ClassWriter.COMPUTE_FRAMES))); } // Collapse tree to bytes byte[] bytes = this.writeClass(targetClass); // Export transformed class for debugging purposes if (MixinTransformer.DEBUG_EXPORT) { try { FileUtils.writeByteArrayToFile( new File(".mixin.out/" + transformedName.replace('.', '/') + ".class"), bytes); } catch (IOException ex) { // don't care } } return bytes; }
From source file:org.spongepowered.asm.transformers.TreeTransformer.java
License:MIT License
/** * @param classNode ClassNode to write out * @return generated bytecode/*w ww .ja v a 2s. c om*/ */ protected final byte[] writeClass(ClassNode classNode) { // Use optimised writer for speed if (this.classReader != null && this.classNode == classNode) { this.classNode = null; ClassWriter writer = new MixinClassWriter(this.classReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); this.classReader = null; classNode.accept(writer); return writer.toByteArray(); } this.classNode = null; ClassWriter writer = new MixinClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); classNode.accept(writer); return writer.toByteArray(); }
From source file:org.spongepowered.granite.launch.transformers.AccessTransformer.java
License:MIT License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null || !this.modifiers.containsKey(transformedName)) { return bytes; }//w ww .j av a 2s. c o m ClassNode classNode = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(classNode, 0); for (Modifier m : this.modifiers.get(transformedName)) { if (m.isClass) { // Class classNode.access = m.transform(classNode.access); } else if (m.desc == null) { // Field for (FieldNode fieldNode : classNode.fields) { if (m.wildcard || fieldNode.name.equals(m.name)) { fieldNode.access = m.transform(fieldNode.access); if (!m.wildcard) { break; } } } } else { List<MethodNode> overridable = null; for (MethodNode methodNode : classNode.methods) { if (m.wildcard || (methodNode.name.equals(m.name) && methodNode.desc.equals(m.desc))) { boolean wasPrivate = (methodNode.access & ACC_PRIVATE) != 0; methodNode.access = m.transform(methodNode.access); // Constructors always use INVOKESPECIAL // if we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL // so that overridden methods will be called. Only need to scan this class, because obviously the method was private. if (!methodNode.name.equals("<init>") && wasPrivate && (methodNode.access & ACC_PRIVATE) == 0) { if (overridable == null) { overridable = new ArrayList<>(3); } overridable.add(methodNode); } if (!m.wildcard) { break; } } } if (overridable != null) { for (MethodNode methodNode : classNode.methods) { for (Iterator<AbstractInsnNode> itr = methodNode.instructions.iterator(); itr.hasNext();) { AbstractInsnNode insn = itr.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode replace : overridable) { if (replace.name.equals(mInsn.name) && replace.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } } } } ClassWriter writer = new ClassWriter(0); classNode.accept(writer); return writer.toByteArray(); }
From source file:org.spongepowered.lantern.launch.AccessTransformer.java
License:MIT License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null || !this.modifiers.containsKey(transformedName)) { return bytes; }//from w w w . j a v a 2 s . c o m ClassNode classNode = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(classNode, 0); for (Modifier m : this.modifiers.get(transformedName)) { if (m.isClass) { // Class classNode.access = m.transform(classNode.access); } else if (m.desc == null) { // Field for (FieldNode fieldNode : classNode.fields) { if (m.wildcard || fieldNode.name.equals(m.name)) { fieldNode.access = m.transform(fieldNode.access); if (!m.wildcard) { break; } } } } else { List<MethodNode> overridable = null; for (MethodNode methodNode : classNode.methods) { if (m.wildcard || (methodNode.name.equals(m.name) && methodNode.desc.equals(m.desc))) { boolean wasPrivate = (methodNode.access & ACC_PRIVATE) != 0; methodNode.access = m.transform(methodNode.access); // Constructors always use INVOKESPECIAL // if we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL // so that overridden methods will be called. Only need to scan this class, because obviously the method was private. if (!methodNode.name.equals("<init>") && wasPrivate && (methodNode.access & ACC_PRIVATE) == 0) { if (overridable == null) { overridable = Lists.newArrayListWithExpectedSize(3); } overridable.add(methodNode); } if (!m.wildcard) { break; } } } if (overridable != null) { for (MethodNode methodNode : classNode.methods) { for (Iterator<AbstractInsnNode> itr = methodNode.instructions.iterator(); itr.hasNext();) { AbstractInsnNode insn = itr.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode replace : overridable) { if (replace.name.equals(mInsn.name) && replace.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } } } } ClassWriter writer = new ClassWriter(0); classNode.accept(writer); return writer.toByteArray(); }
From source file:org.spongepowered.lwts.transformer.AccessTransformer.java
License:MIT License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (this.modifiers == null) { this.modifiers = this.processor.build(); this.processor = null; }/*ww w .j a va 2s . co m*/ if (bytes == null || !this.modifiers.containsKey(transformedName)) { return bytes; } ClassNode classNode = new ClassNode(); ClassReader reader = new ClassReader(bytes); reader.accept(classNode, 0); for (Modifier m : this.modifiers.get(transformedName)) { if (m.isClass) { // Class classNode.access = m.transform(classNode.access); } else if (m.desc == null) { // Field for (FieldNode fieldNode : classNode.fields) { if (m.wildcard || fieldNode.name.equals(m.name)) { fieldNode.access = m.transform(fieldNode.access); if (!m.wildcard) { break; } } } } else { List<MethodNode> overridable = null; for (MethodNode methodNode : classNode.methods) { if (m.wildcard || (methodNode.name.equals(m.name) && methodNode.desc.equals(m.desc))) { boolean wasPrivate = (methodNode.access & ACC_PRIVATE) != 0; methodNode.access = m.transform(methodNode.access); // Constructors always use INVOKESPECIAL // if we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL // so that overridden methods will be called. Only need to scan this class, because obviously the method was private. if (!methodNode.name.equals("<init>") && wasPrivate && (methodNode.access & ACC_PRIVATE) == 0) { if (overridable == null) { overridable = Lists.newArrayListWithExpectedSize(3); } overridable.add(methodNode); } if (!m.wildcard) { break; } } } if (overridable != null) { for (MethodNode methodNode : classNode.methods) { for (Iterator<AbstractInsnNode> itr = methodNode.instructions.iterator(); itr.hasNext();) { AbstractInsnNode insn = itr.next(); if (insn.getOpcode() == INVOKESPECIAL) { MethodInsnNode mInsn = (MethodInsnNode) insn; for (MethodNode replace : overridable) { if (replace.name.equals(mInsn.name) && replace.desc.equals(mInsn.desc)) { mInsn.setOpcode(INVOKEVIRTUAL); break; } } } } } } } } ClassWriter writer = new ClassWriter(0); classNode.accept(writer); return writer.toByteArray(); }
From source file:org.spongepowered.mod.asm.transformers.BaseEventTransformer.java
License:MIT License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null || name == null) { return bytes; }/* w w w . j a v a2 s .com*/ try { ClassReader cr = new ClassReader(bytes); ClassNode classNode = new ClassNode(); cr.accept(classNode, 0); String parentName = classNode.superName.replace('/', '.'); Class<?> parent = this.getClass().getClassLoader().loadClass(parentName); // Skip classes that do not implement SpongeAPI Event, or extend other classes // This implies that there will be issues with custom event classes that extend a superclass that does not fit these conditions itself // However, this is a fairly fundamental JVM limitation if ((!Object.class.equals(parent.getSuperclass())) || (!Event.class.isAssignableFrom(parent))) { return bytes; } // Add forwarding methods ASMHelper.addAndReplaceMethod(classNode, EventTransformer.createGetGameMethod()); ASMHelper.addAndReplaceMethod(classNode, EventTransformer.createGetSimpleNameMethod()); ASMHelper.addAndReplaceMethod(classNode, EventTransformer.createIsCancellableMethod()); ASMHelper.addAndReplaceMethod(classNode, EventTransformer.createIsCancelledMethod()); ASMHelper.addAndReplaceMethod(classNode, EventTransformer.createSetCancelledMethod()); // Change super-class classNode.superName = "net/minecraftforge/fml/common/eventhandler/Event"; // Replace super() call in constructor so that it points to the new super-class MethodNode method = ASMHelper.findMethod(classNode, "<init>", "()V"); ListIterator<AbstractInsnNode> instructions = method.instructions.iterator(); while (instructions.hasNext()) { AbstractInsnNode insn = instructions.next(); if (insn.getOpcode() == Opcodes.INVOKESPECIAL) { MethodInsnNode methodInsn = new MethodInsnNode(Opcodes.INVOKESPECIAL, classNode.superName, "<init>", "()V", false); instructions.remove(); instructions.add(methodInsn); break; } } ClassWriter cw = new ClassWriter(cr, COMPUTE_MAXS | COMPUTE_FRAMES); classNode.accept(cw); return cw.toByteArray(); } catch (Throwable t) { t.printStackTrace(); return bytes; } }
From source file:org.spongepowered.mod.asm.transformers.EventTransformer.java
License:MIT License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null || transformedName.startsWith("net.minecraft.") || transformedName.equals("net.minecraftforge.fml.common.event.FMLEvent") || transformedName.equals("net.minecraftforge.fml.common.eventhandler.Event") || transformedName.indexOf('.') == -1) { return bytes; }//from w w w. ja v a 2 s . c o m try { ClassReader cr = new ClassReader(bytes); ClassNode classNode = new ClassNode(); cr.accept(classNode, 0); String parentName = classNode.superName.replace('/', '.'); Class<?> parent = this.getClass().getClassLoader().loadClass(parentName); // Only process FMLEvents and Forge Events sub-classes if ((!Event.class.isAssignableFrom(parent)) && (!FMLEvent.class.isAssignableFrom(parent))) { return bytes; } Class<?> interf = events.get(transformedName); if (interf != null && interf.isInterface()) { String interfaceName = Type.getInternalName(interf); classNode.interfaces.add(interfaceName); } // Method forwarding for all events classNode.methods.add(createGetGameMethod()); classNode.methods.add(createGetSimpleNameMethod()); if (Event.class.isAssignableFrom(parent)) { // Forge Event method forwarding if (classNode.interfaces.contains("org/spongepowered/api/event/Cancellable")) { if (classNode.visibleAnnotations == null) { classNode.visibleAnnotations = new ArrayList<AnnotationNode>(); } classNode.visibleAnnotations .add(new AnnotationNode("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;")); classNode.methods.add(createIsCancelledMethod()); classNode.methods.add(createSetCancelledMethod()); } classNode.methods.add(createIsCancellableMethod()); } // TODO: This is a temporary thing to make PreInit work. The different things needed to make different events work should be abstracted. if (interf != null && PreInitializationEvent.class.isAssignableFrom(interf)) { ASMHelper.generateSelfForwardingMethod(classNode, "getConfigurationDirectory", "getModConfigurationDirectory", Type.getType(File.class)); ASMHelper.generateSelfForwardingMethod(classNode, "getPluginLog", "getModLog", Type.getType(Logger.class)); } ClassWriter cw = new ClassWriter(cr, COMPUTE_MAXS | COMPUTE_FRAMES); classNode.accept(cw); return cw.toByteArray(); } catch (Throwable t) { t.printStackTrace(); return bytes; } }
From source file:org.spongepowered.mod.asm.transformers.PriorityTransformer.java
License:MIT License
@Override public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null || !name.equals("cpw.mods.fml.common.eventhandler.EventPriority")) { return bytes; }/*from w w w . jav a2 s. c om*/ try { ClassReader cr = new ClassReader(bytes); ClassNode classNode = new ClassNode(); cr.accept(classNode, 0); ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); CheckClassAdapter checker = new CheckClassAdapter(cw); classNode.accept(checker); return cw.toByteArray(); } catch (Throwable t) { t.printStackTrace(); return bytes; } }
From source file:org.spongepowered.mod.asm.transformers.TreeTransformer.java
License:MIT License
/** * @param classNode//from ww w . java 2 s . c om * @return */ protected final byte[] writeClass(ClassNode classNode) { // Use optimised writer for speed if (this.classReader != null && this.classNode == classNode) { this.classNode = null; ClassWriter writer = new ClassWriter(this.classReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); this.classReader = null; classNode.accept(writer); return writer.toByteArray(); } this.classNode = null; ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); classNode.accept(writer); return writer.toByteArray(); }