创建 MethodNode 失败并出现 IllegalStateException
Creating MethodNode fails with IllegalStateException
我想得到 main()
函数的 MethodNode
public class TestMethodNode {
public void main() {
}
}
所以我尝试了这个
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.MethodNode;
import static org.objectweb.asm.Opcodes.ASM7;
import java.io.IOException;
public class Instrumentation {
public byte[] editFunction(String className) throws IOException {
byte[] modifiedClass = null;
try {
ClassReader classReader = new ClassReader(className);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
ClassVisitor classAdapter = new ClassVisitor(ASM7, classWriter) {
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions) {
if (name.equals("main")) {
final MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
MethodNode methodNode = new MethodNode(access, name, desc, signature, exceptions) {
public void visitEnd() {
// transform / analyze method here
accept(methodVisitor);
}
};
return methodNode;
} else {
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
};
classReader.accept(classAdapter, 0);
modifiedClass = classWriter.toByteArray();
} catch (IOException ex) {
throw ex;
}
return modifiedClass;
}
}
并在创建 MethodNode
时从 .../asm/tree/MethodNode.java 获得 IllegalStateException
public MethodNode(
final int access,
final String name,
final String descriptor,
final String signature,
final String[] exceptions) {
this(Opcodes.ASM7, access, name, descriptor, signature, exceptions);
if (getClass() != MethodNode.class) {
throw new IllegalStateException();
}
}
我做错了什么? (我不想破解 Minecraft,我正在研究并尝试操纵涉及 lambda 表达式和嵌套/内部 类 的调用堆栈,用于在运行时使用字节码操作的工作流引擎。)
… Subclasses must not use this constructor. Instead, they must use the MethodNode(int, int, String, String, String, String[])
version.
由于是创建子类,所以要改调用
new MethodNode(access, name, desc, signature, exceptions) {
…
}
至
new MethodNode(ASM7, access, name, desc, signature, exceptions) {
…
}
只是为给定 class
的仪器函数 main()
提供完整的 运行 样本
public class Instrumentation {
public byte[] instrument(String className) {
byte[] modifiedClass = null;
try {
ClassReader classReader = new ClassReader(className);
ClassWriter classWriter = new ClassWriter(classReader, 4);
ClassVisitor classVisitor = new ClassVisitor(ASM7) {
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions) {
if (name.equals("main")) {
MethodNode methodNode = new MethodNode(ASM7,access, name, desc, signature, exceptions) {
public void visitEnd() {
// do some stuff here; remove exceptions, insnnode etc. -- smaple iterates through instructions
for (int i = 0; i < this.instructions.size();i++) {
AbstractInsnNode node = this.instructions.get(i);
}
}
};
return methodNode;
} else {
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
};
classReader.accept(classVisitor,0);
classReader.accept(classWriter, 0);
modifiedClass = classWriter.toByteArray();
} catch (IOException ex) {
// handle IOException here
}
return modifiedClass;
}
}
我想得到 main()
函数的 MethodNode
public class TestMethodNode {
public void main() {
}
}
所以我尝试了这个
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.MethodNode;
import static org.objectweb.asm.Opcodes.ASM7;
import java.io.IOException;
public class Instrumentation {
public byte[] editFunction(String className) throws IOException {
byte[] modifiedClass = null;
try {
ClassReader classReader = new ClassReader(className);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
ClassVisitor classAdapter = new ClassVisitor(ASM7, classWriter) {
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions) {
if (name.equals("main")) {
final MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
MethodNode methodNode = new MethodNode(access, name, desc, signature, exceptions) {
public void visitEnd() {
// transform / analyze method here
accept(methodVisitor);
}
};
return methodNode;
} else {
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
};
classReader.accept(classAdapter, 0);
modifiedClass = classWriter.toByteArray();
} catch (IOException ex) {
throw ex;
}
return modifiedClass;
}
}
并在创建 MethodNode
IllegalStateException
public MethodNode(
final int access,
final String name,
final String descriptor,
final String signature,
final String[] exceptions) {
this(Opcodes.ASM7, access, name, descriptor, signature, exceptions);
if (getClass() != MethodNode.class) {
throw new IllegalStateException();
}
}
我做错了什么? (我不想破解 Minecraft,我正在研究并尝试操纵涉及 lambda 表达式和嵌套/内部 类 的调用堆栈,用于在运行时使用字节码操作的工作流引擎。)
… Subclasses must not use this constructor. Instead, they must use the
MethodNode(int, int, String, String, String, String[])
version.
由于是创建子类,所以要改调用
new MethodNode(access, name, desc, signature, exceptions) {
…
}
至
new MethodNode(ASM7, access, name, desc, signature, exceptions) {
…
}
只是为给定 class
的仪器函数main()
提供完整的 运行 样本
public class Instrumentation {
public byte[] instrument(String className) {
byte[] modifiedClass = null;
try {
ClassReader classReader = new ClassReader(className);
ClassWriter classWriter = new ClassWriter(classReader, 4);
ClassVisitor classVisitor = new ClassVisitor(ASM7) {
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions) {
if (name.equals("main")) {
MethodNode methodNode = new MethodNode(ASM7,access, name, desc, signature, exceptions) {
public void visitEnd() {
// do some stuff here; remove exceptions, insnnode etc. -- smaple iterates through instructions
for (int i = 0; i < this.instructions.size();i++) {
AbstractInsnNode node = this.instructions.get(i);
}
}
};
return methodNode;
} else {
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
};
classReader.accept(classVisitor,0);
classReader.accept(classWriter, 0);
modifiedClass = classWriter.toByteArray();
} catch (IOException ex) {
// handle IOException here
}
return modifiedClass;
}
}