我是java新手,(我用.NET编程,Lua ...),我开始使用ASM。 所以我不能使用“Foo”类的任何方法,我如何调用这些方法?
非常感谢...代码:
package com.teste;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Opcodes.*;
public class nclass {
public static void main(String[] args) throws Exception {
Class<?> klass = new ClassLoader(nclass.class.getClassLoader()) {
public Class<?> defineClass() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
//
Label l0;
Label l1;
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
"Foo", null, "java/lang/Object", null);
for (int i = 0; i < 3; i++) {
fv = cw.visitField(0, "value" + i, "I", null, null);
fv.visitAnnotation("LBar;", true).visitEnd();
}
fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "nome", "Ljava/lang/String;", null, null);
fv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(2, l0);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(Opcodes.RETURN);
l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "Lsimple;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "setNome", "(Ljava/lang/String;)V", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(6, l0);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.PUTSTATIC, "simple", "nome", "Ljava/lang/String;");
mv.visitInsn(Opcodes.RETURN);
l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("value", "Ljava/lang/String;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "getNome", "()Ljava/lang/String;", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(7, l0);
mv.visitFieldInsn(Opcodes.GETSTATIC, "simple", "nome", "Ljava/lang/String;");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 0);
mv.visitEnd();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
return defineClass("Foo", bytes, 0, bytes.length);
}
}.defineClass();
for (Field f : klass.getDeclaredFields()) {
System.out.println(f + " " + Arrays.toString(f.getAnnotations()));
}
for (Field f : klass.getDeclaredFields()) {
System.out.println(f + " " + f.getName());
}
for (Method f : klass.getDeclaredMethods()) {
System.out.println(f + " " + Arrays.toString(f.getAnnotations()));
}
Class<?> c= klass.forName("Foo");
Method method = c.getDeclaredMethod ("getNome", String.class);
System.out.println(method.invoke(c));
}
}
*新代码工作*
package com;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Opcodes.*;
public class simple {
/**
* @param args
* @throws NoSuchMethodException
* @throws SecurityException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Class<?> klass = new ClassLoader(simple.class.getClassLoader()) {
public Class<?> defineClass() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
//
Label l0;
Label l1;
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
"simple", null, "java/lang/Object", null);
for (int i = 0; i < 3; i++) {
fv = cw.visitField(0, "value" + i, "I", null, null);
fv.visitAnnotation("LBar;", true).visitEnd();
}
fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "nome", "Ljava/lang/String;", null, null);
fv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(2, l0);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(Opcodes.RETURN);
l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "Lsimple;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "setNome", "(Ljava/lang/String;)V", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(6, l0);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.PUTSTATIC, "simple", "nome", "Ljava/lang/String;");
mv.visitInsn(Opcodes.RETURN);
l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("value", "Ljava/lang/String;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "getNome", "()Ljava/lang/String;", null, null);
mv.visitCode();
l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(7, l0);
mv.visitFieldInsn(Opcodes.GETSTATIC, "simple", "nome", "Ljava/lang/String;");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 0);
mv.visitEnd();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
return defineClass("simple", bytes, 0, bytes.length);
}
}.defineClass();
for (Field f : klass.getDeclaredFields()) {
System.out.println(f + " " + Arrays.toString(f.getAnnotations()));
}
for (Field f : klass.getDeclaredFields()) {
System.out.println(f + " " + f.getName());
}
for (Method f : klass.getDeclaredMethods()) {
System.out.println(f + " " + Arrays.toString(f.getAnnotations()));
}
Method setNome = klass.getDeclaredMethod("setNome", String.class);
Method getNome = klass.getDeclaredMethod("getNome");
setNome.invoke(klass,"this sucks!");
System.out.println(getNome.invoke(null));
}
}
感谢PaŭloEbermann,下一步我将尝试使用实例加载类(我认为类似“Class s = new simple()”)。
答案 0 :(得分:2)
看起来你的问题就在这里:
Class<?> c= klass.forName("Foo");
Method method = c.getDeclaredMethod ("getNome", String.class);
System.out.println(method.invoke(c));
klass.forName("Foo")
实际上相当于Class.forName("Foo")
,结果为Class.forName("Foo", nclass.class.getClassLoader());
。
加载nclass
的类加载器显然不知道Foo
类,因为它是由您的匿名类加载器(它是此类加载器的子级)创建的。因此,请不要在此处使用此forName
调用,只需使用您的klass
对象来获取方法并调用它。
当然,调用和检索方法与您的方法不同。
getMethod
和getDeclaredMethod
在名称旁边加上参数类型列表(不是返回类型) - 在您的情况下getNome
没有参数,所以它应该是:
Method method = klass.getDeclaredMethod ("getNome");
invoke方法第一个参数是接收类型(在您的情况下为Foo
)的方法的对象,或者是静态方法的null
。以下参数是方法的参数(即在您的情况下没有)。所以你应该在这里使用:
System.out.println(method.invoke(null));
在您的情况下,可能只是忽略了参数,因此c
可能不会出错。但是如果你实际上没有通过反射调用类Class
的方法,那么仍然没有理由在这里使用类对象。
这一切都假设您的forName
电话中发生了错误,而且之前尚未发生错误。请学习描述您的错误消息,因此我们不必猜测。