2011-03-30 12 views
1

私はJavaに新しい(私は.NETでプログラミングするために使用する、ルア...)と私はASMを使い始めた。 私はクラス "Foo"のメソッドを使用することはできません、どうすればこれらのメソッドを呼び出すことができますか?バイトコードクラスのメソッドを呼び出す、java

多くのおかげで...

コード:

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); 
      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)); 

} 

} 

おかげPAULO Ebermannは、次のステップは、私は(インスタンスとクラスのロードを試みるでしょう私は "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", nclass.class.getClassLoader());になりClass.forName("Foo")、と実際に同等です。

nclassをロードしたクラスローダーは、匿名クラスローダー(このクラスローダーの子)によって作成されたため、明らかにFooクラスを認識しません。だから、ここでこのforNameコールを使用しないでください。単にklassオブジェクトを使用してメソッドを取得し、呼び出すだけです。


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

  • getMethodgetDeclaredMethod名の横に引数の型(タイプを返さない)のリストを取る - それがあるべきように、あなたのケースでgetNomeは、引数がない:

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

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

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

すべてはあなたのエラーを想定している。この

はなく、すでに以前ご forName呼び出しで発生します。エラーメッセージの説明を覚えておいてください。推測する必要はありません。

+0

私はバグを見つけました。私はいくつかの宣言を "シンプル"と "フー"と混乱させてしまい、エラーが発生しました。 ... – xxleite