use of org.objectweb.asm.tree.MethodNode in project enumerable by hraberg.
the class LambdaExpressionTrees method findMethodNode.
@SuppressWarnings("unchecked")
static MethodNode findMethodNode(Method method) throws IOException {
String className = method.getDeclaringClass().getName();
ClassReader cr;
if (InMemoryCompiler.bytesByClassName.containsKey(className))
cr = new ClassReader(InMemoryCompiler.bytesByClassName.get(className));
else
cr = new ClassReader(className);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
String descriptor = getMethodDescriptor(method);
for (MethodNode mn : (List<MethodNode>) cn.methods) {
if (method.getName().equals(mn.name) && descriptor.equals(mn.desc))
return mn;
}
throw new IllegalStateException("Cannot find method which does exist");
}
use of org.objectweb.asm.tree.MethodNode in project MinecraftForge by MinecraftForge.
the class EventSubscriptionTransformer method buildEvents.
private boolean buildEvents(ClassNode classNode) throws Exception {
// Yes, this recursively loads classes until we get this base class. THIS IS NOT A ISSUE. Coremods should handle re-entry just fine.
// If they do not this a COREMOD issue NOT a Forge/LaunchWrapper issue.
Class<?> parent = this.getClass().getClassLoader().loadClass(classNode.superName.replace('/', '.'));
if (!Event.class.isAssignableFrom(parent)) {
return false;
}
//Class<?> listenerListClazz = Class.forName("net.minecraftforge.fml.common.eventhandler.ListenerList", false, getClass().getClassLoader());
Type tList = Type.getType("Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
boolean edited = false;
boolean hasSetup = false;
boolean hasGetListenerList = false;
boolean hasDefaultCtr = false;
boolean hasCancelable = false;
boolean hasResult = false;
String voidDesc = Type.getMethodDescriptor(VOID_TYPE);
String boolDesc = Type.getMethodDescriptor(BOOLEAN_TYPE);
String listDesc = tList.getDescriptor();
String listDescM = Type.getMethodDescriptor(tList);
for (MethodNode method : classNode.methods) {
if (method.name.equals("setup") && method.desc.equals(voidDesc) && (method.access & ACC_PROTECTED) == ACC_PROTECTED)
hasSetup = true;
if ((method.access & ACC_PUBLIC) == ACC_PUBLIC) {
if (method.name.equals("getListenerList") && method.desc.equals(listDescM))
hasGetListenerList = true;
if (method.name.equals("isCancelable") && method.desc.equals(boolDesc))
hasCancelable = true;
if (method.name.equals("hasResult") && method.desc.equals(boolDesc))
hasResult = true;
}
if (method.name.equals("<init>") && method.desc.equals(voidDesc))
hasDefaultCtr = true;
}
if (classNode.visibleAnnotations != null) {
for (AnnotationNode node : classNode.visibleAnnotations) {
if (!hasResult && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Event$HasResult;")) {
/* Add:
* public boolean hasResult()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "hasResult", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
} else if (!hasCancelable && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;")) {
/* Add:
* public boolean isCancelable()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "isCancelable", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
}
}
}
if (hasSetup) {
if (!hasGetListenerList)
throw new RuntimeException("Event class defines setup() but does not define getListenerList! " + classNode.name);
else
return edited;
}
Type tSuper = Type.getType(classNode.superName);
//Add private static ListenerList LISTENER_LIST
classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null));
/*Add:
* public <init>()
* {
* super();
* }
*/
if (!hasDefaultCtr) {
MethodNode method = new MethodNode(ACC_PUBLIC, "<init>", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "<init>", voidDesc, false));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
}
/*Add:
* protected void setup()
* {
* super.setup();
* if (LISTENER_LIST != NULL)
* {
* return;
* }
* LISTENER_LIST = new ListenerList(super.getListenerList());
* }
*/
MethodNode method = new MethodNode(ACC_PROTECTED, "setup", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "setup", voidDesc, false));
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
LabelNode initListener = new LabelNode();
method.instructions.add(new JumpInsnNode(IFNULL, initListener));
method.instructions.add(new InsnNode(RETURN));
method.instructions.add(initListener);
method.instructions.add(new FrameNode(F_SAME, 0, null, 0, null));
method.instructions.add(new TypeInsnNode(NEW, tList.getInternalName()));
method.instructions.add(new InsnNode(DUP));
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "getListenerList", listDescM, false));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tList.getInternalName(), "<init>", getMethodDescriptor(VOID_TYPE, tList), false));
method.instructions.add(new FieldInsnNode(PUTSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
/*Add:
* public ListenerList getListenerList()
* {
* return this.LISTENER_LIST;
* }
*/
method = new MethodNode(ACC_PUBLIC, "getListenerList", listDescM, null, null);
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(ARETURN));
classNode.methods.add(method);
return true;
}
use of org.objectweb.asm.tree.MethodNode in project MinecraftForge by MinecraftForge.
the class SideTransformer method transform.
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (bytes == null) {
return null;
}
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
if (remove(classNode.visibleAnnotations, SIDE)) {
if (DEBUG) {
System.out.println(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE));
}
throw new RuntimeException(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE));
}
Iterator<FieldNode> fields = classNode.fields.iterator();
while (fields.hasNext()) {
FieldNode field = fields.next();
if (remove(field.visibleAnnotations, SIDE)) {
if (DEBUG) {
System.out.println(String.format("Removing Field: %s.%s", classNode.name, field.name));
}
fields.remove();
}
}
LambdaGatherer lambdaGatherer = new LambdaGatherer();
Iterator<MethodNode> methods = classNode.methods.iterator();
while (methods.hasNext()) {
MethodNode method = methods.next();
if (remove(method.visibleAnnotations, SIDE)) {
if (DEBUG) {
System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc));
}
methods.remove();
lambdaGatherer.accept(method);
}
}
// remove dynamic lambda methods that are inside of removed methods
List<Handle> dynamicLambdaHandles = lambdaGatherer.getDynamicLambdaHandles();
if (!dynamicLambdaHandles.isEmpty()) {
methods = classNode.methods.iterator();
while (methods.hasNext()) {
MethodNode method = methods.next();
for (Handle dynamicLambdaHandle : dynamicLambdaHandles) {
if (method.name.equals(dynamicLambdaHandle.getName()) && method.desc.equals(dynamicLambdaHandle.getDesc())) {
if (DEBUG) {
System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc));
}
methods.remove();
}
}
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
use of org.objectweb.asm.tree.MethodNode in project LogisticsPipes by RS485.
the class LogisticsClassTransformer method handleWorldClass.
private byte[] handleWorldClass(byte[] bytes) {
final ClassReader reader = new ClassReader(bytes);
final ClassNode node = new ClassNode();
reader.accept(node, 0);
for (MethodNode m : node.methods) {
if (m.name.equals("notifyBlocksOfNeighborChange") || m.name.equals("func_147459_d") || (m.name.equals("d") && m.desc.equals("(IIILaji;)V"))) {
MethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {
@Override
public void visitCode() {
super.visitCode();
Label l0 = new Label();
visitLabel(l0);
visitVarInsn(Opcodes.ALOAD, 0);
visitVarInsn(Opcodes.ILOAD, 1);
visitVarInsn(Opcodes.ILOAD, 2);
visitVarInsn(Opcodes.ILOAD, 3);
this.visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/LogisticsASMHookClass", "notifyBlocksOfNeighborChange_Start", "(Lnet/minecraft/world/World;III)V");
}
@Override
public void visitInsn(int opcode) {
if (opcode == Opcodes.RETURN) {
visitVarInsn(Opcodes.ALOAD, 0);
visitVarInsn(Opcodes.ILOAD, 1);
visitVarInsn(Opcodes.ILOAD, 2);
visitVarInsn(Opcodes.ILOAD, 3);
this.visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/LogisticsASMHookClass", "notifyBlocksOfNeighborChange_Stop", "(Lnet/minecraft/world/World;III)V");
Label l0 = new Label();
visitLabel(l0);
}
super.visitInsn(opcode);
}
};
m.accept(mv);
node.methods.set(node.methods.indexOf(m), mv);
}
if (m.name.equals("notifyBlockOfNeighborChange") || m.name.equals("func_147460_e") || (m.name.equals("e") && m.desc.equals("(IIILaji;)V"))) {
MethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {
boolean done = false;
@Override
public void visitLabel(Label label) {
if (!done) {
done = true;
Label l0 = new Label();
visitLabel(l0);
visitVarInsn(Opcodes.ALOAD, 0);
visitVarInsn(Opcodes.ILOAD, 1);
visitVarInsn(Opcodes.ILOAD, 2);
visitVarInsn(Opcodes.ILOAD, 3);
this.visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/LogisticsASMHookClass", "notifyBlockOfNeighborChange", "(Lnet/minecraft/world/World;III)V");
}
super.visitLabel(label);
}
};
m.accept(mv);
node.methods.set(node.methods.indexOf(m), mv);
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
node.accept(writer);
return writer.toByteArray();
}
use of org.objectweb.asm.tree.MethodNode in project Minechem by iopleke.
the class MinechemTransformer method injectBytes.
private byte[] injectBytes(Method method, InstructionNode instructionNode, byte[] data) {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(data);
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
MethodNode methodNode = getMethodByName(classNode, method);
AbstractInsnNode pos = findInstructionNode(instructionNode, methodNode);
if (instructionNode.replace) {
methodNode.instructions.insertBefore(pos, instructionNode.getInsnList());
methodNode.instructions.remove(pos);
} else {
methodNode.instructions.insertBefore(pos, instructionNode.getInsnList());
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
Aggregations