Invoke a bytecode class method, java
Im new to java, (i use to program in .NET, Lua ...) and i started to use ASM. so i can't use any methods of the class "Foo", how can i invoke these methods?
many thanks...
code:
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));
}
}
* NEW CODE WORKING *
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);
m开发者_开发问答v.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));
}
}
Thanks Paŭlo Ebermann, next step i ll try class loading with instance ( i think something like "Class s= new simple()" ).
It looks like your problem is here:
Class<?> c= klass.forName("Foo");
Method method = c.getDeclaredMethod ("getNome", String.class);
System.out.println(method.invoke(c));
klass.forName("Foo")
is actually equivalent to Class.forName("Foo")
, which results in Class.forName("Foo", nclass.class.getClassLoader());
.
The class loader which loaded nclass
obviously does not know a Foo
class, since it was created by your anonymous class loader (which is a child of this class loader). So, don't use this forName
call here, but simply use your klass
object to get the method and invoke it.
And of course, invoking and retrieving a method works not like you did.
The
getMethod
andgetDeclaredMethod
take beside the name a list of argument types (not return types) - in your casegetNome
has no arguments, so it should be:Method method = klass.getDeclaredMethod ("getNome");
the invoke methods first argument is an object of the methods receiving type (
Foo
in your case), ornull
for static methods. The following arguments are the parameters to the method (i.e. none in your case). So you should use here:System.out.println(method.invoke(null));
It may be that the argument is simply ignored in your case, so
c
might not get an error. But there still is no reason to use a class object here, if you are not actually invoking a method of classClass
by reflection.
This all is assuming your error occurs in your forName
call and not already earlier. Please learn to describe your error message, so we don't have to guess.
精彩评论