1

私は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()"のようなものだと思います)。

4

1 に答える 1

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オブジェクトを使用してメソッドを取得し、それを呼び出します。


そしてもちろん、メソッドの呼び出しと取得は、あなたが行ったようには機能しません。

  • 名前の横getMethodgetDeclaredMethodある引数タイプのリスト(戻り型ではない)-この場合getNome、引数がないため、次のようになります。

    Method  method = klass.getDeclaredMethod ("getNome");
    
  • invokeメソッドの最初の引数は、メソッド受信タイプ(Fooこの場合)のオブジェクト、またはnull静的メソッドのオブジェクトです。次の引数は、メソッドのパラメーターです(つまり、この場合はなし)。したがって、ここで使用する必要があります。

    System.out.println(method.invoke(null));
    

    あなたの場合、引数が単に無視されているc可能性があるため、エラーが発生しない可能性があります。Classただし、リフレクションによってクラスのメソッドを実際に呼び出していない場合は、ここでクラスオブジェクトを使用する理由はまだありません。

これはすべて、あなたのエラーがあなたのforName呼び出しで発生し、まだ以前ではないことを前提としています。推測する必要がないように、エラーメッセージの説明を学んでください。

于 2011-03-30T22:08:54.227 に答える