gpt4 book ai didi

java - 调用字节码类方法,java

转载 作者:行者123 更新时间:2023-11-30 05:04:42 24 4
gpt4 key购买 nike

我是 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ŭlo Ebermann,下一步我将尝试使用实例加载类(我认为类似于“Class s= new simple()”)。

最佳答案

看来您的问题在这里:

 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");
  • 调用方法的第一个参数是方法接收类型的对象(在您的情况下是Foo),或者静态方法的null。以下参数是该方法的参数(即在您的情况下没有参数)。所以你应该在这里使用:

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

    在您的情况下,该参数可能会被忽略,因此 c 可能不会出现错误。但是,如果您实际上没有通过反射调用 Class 类的方法,那么仍然没有理由在这里使用类对象。

这一切都假设您的错误发生在您的 forName 调用中,而不是更早发生。请学会描述您的错误消息,以便我们不必猜测。

关于java - 调用字节码类方法,java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5492872/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com