现在用asm生成class文件,但是不知道怎么生成实现接口,也就生成某个类,然后这个类实现某一接口另,asm生成double类型报错,估计是ILOAD那边的事,但是不知道该填什么参数,谢谢

解决方案 »

  1.   

    实现接口不就是在参数中指定就行了吗? 当然还得自己添加接口的方法ClassWriter cw=new ClassWriter(0);
    cw.visit(0x31,Modifier.PUBLIC,"Example",null,"java/lang/Object",new String[]{"java/lang/Cloneable"});
      

  2.   

    不知你的double报错是啥意思   我猜是 ILOAD  改成 DLOAD
      

  3.   

    谢谢 houjin_cn
    我改成DLOAD报错,不改还是ILOAD也报错
    Arguments can't fit into locals in class file报这个错,另外我是直接拿INT类型的代码复制过去的就把类型从I改为D
    谢谢
      

  4.   


    String field = "test";
    Object defaultValue = 123d;
    String setMd = "set" + StringUtils.capitalize(field);
    String getMd = "get" + StringUtils.capitalize(field);
    cw.visitField(
    ACC_PRIVATE,
    field,
    "D",
    null,
    defaultValue == null ? null : Double.parseDouble(defaultValue.toString())).visitEnd(); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, getMd, "()D", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, field, "D");
    mv.visitInsn(IRETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
    cw.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, setMd, "(D)V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ILOAD, 1);
    mv.visitFieldInsn(PUTFIELD, className, field, "D");
    mv.visitInsn(RETURN);
    mv.visitMaxs(2, 2);
    // variables
    mv.visitEnd();
    这是我的代码生成时报错,默认值也不管用
      

  5.   

     mv.visitVarInsn(ALOAD, 0);
     mv.visitVarInsn(ILOAD, 1);
    这两行不知道是啥意思,不知道字段为String int double 的时候这设置是否一样
      

  6.   

    如果是INT类型的代码复制过去的花,  
    mv.visitMaxs(1, 1); 和 mv.visitMaxs(2, 2); 要分别改成
    mv.visitMaxs(2, 2); 和 mv.visitMaxs(3, 3);
      

  7.   

    非常感谢                String field = "test";
    Object defaultValue = 123d;
    String setMd = "set" + StringUtils.capitalize(field);
    String getMd = "get" + StringUtils.capitalize(field);
    cw.visitField(
    ACC_PRIVATE,
    field,
    "D",
    null,
    defaultValue == null ? null : Double.parseDouble(defaultValue
    .toString())).visitEnd(); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, getMd, "()D", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, className, field, "D");
    mv.visitInsn(IRETURN);
    mv.visitMaxs(2, 2);
    mv.visitEnd();
    cw.visitEnd(); mv = cw.visitMethod(ACC_PUBLIC, setMd, "(D)V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ILOAD, 1);
    mv.visitFieldInsn(PUTFIELD, className, field, "D");
    mv.visitInsn(RETURN);
    mv.visitMaxs(3, 3);
    // variables
    mv.visitEnd();
    我是这样的,运行报错
    Exception in thread "main" java.lang.VerifyError: (class: cn/gql/entity/UserInfo, method: setTest0 signature: (D)V) Register 1 contains wrong type
    可否把帖出代码看下,是不是我哪还错着呢
      

  8.   

    参考我的测试代码import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.Opcodes;public class TestAsm implements Opcodes{
    public static void main(String[] args) throws InstantiationException, IllegalAccessException{
    ClassWriter cw=new ClassWriter(0);
    String className="Example";
    cw.visit(0x31,ACC_PUBLIC,className,null,"java/lang/Object",new String[]{"java/lang/Cloneable",ITest.class.getName().replace('.','/')}); String field="test";
    Object defaultValue=123d;
    String setMd="setTest";
    String getMd="getTest";
    cw.visitField(ACC_PRIVATE,field,"D",null,defaultValue == null?null:Double.parseDouble(defaultValue.toString())).visitEnd();
    MethodVisitor mv=cw.visitMethod(ACC_PUBLIC,getMd,"()D",null,null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD,0);
    mv.visitFieldInsn(GETFIELD,className,field,"D");
    mv.visitInsn(DRETURN);
    mv.visitMaxs(2,2);
    mv.visitEnd();
    cw.visitEnd(); mv=cw.visitMethod(ACC_PUBLIC,setMd,"(D)V",null,null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD,0);
    mv.visitVarInsn(DLOAD,1);
    mv.visitFieldInsn(PUTFIELD,className,field,"D");
    mv.visitInsn(RETURN);
    mv.visitMaxs(3,3);
    mv.visitEnd();


    //下面产生构造方法
    mv=cw.visitMethod(ACC_PUBLIC,"<init>","()V",null,null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD,0);
    mv.visitMethodInsn(INVOKESPECIAL,"java/lang/Object","<init>","()V");
    mv.visitInsn(RETURN);
    mv.visitMaxs(1,1);
    mv.visitEnd();


    cw.visitEnd(); byte[] bs=cw.toByteArray();
    //FileUtil.writeFile("d:/test/asm/Example.class",bs);

    MyCLassLoader loader=new MyCLassLoader();
    Class c=loader.defineClass(bs);

    ITest ins=(ITest)c.newInstance();
    ins.setTest(100.0d);
    System.out.println(ins.getTest());
    } public interface ITest{
    public double getTest();
    public void setTest(double d);
    } public static class MyCLassLoader extends ClassLoader{
    public Class defineClass(byte[] data){
    return super.defineClass(null,data,0,data.length,null);
    }
    }
    }
      

  9.   

    谢谢已经可能生存, 但是设置的默认值好像不能用呢
    如果不执行 ins.setTest(100.0d);则打印出的是0.0 ,不知道是哪的事?
      

  10.   

    默认值还是没搞定,
    cw.visitField(ACC_PRIVATE,field,"D",null,defaultValue == null?null:Double.parseDouble(defaultValue.toString())).visitEnd();
    这是给字段赋了默认值了,但是打印出来的还是0.0,不知道哪的事
      

  11.   

    改进了一下, 在构造方法中赋默认值
    import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.Opcodes;public class TestAsm implements Opcodes{
    public static void main(String[] args) throws Exception{
    ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_MAXS);//这样设置才能自动计算
    String className="Example";
    cw.visit(V1_5,ACC_PUBLIC,className,null,"java/lang/Object",new String[]{"java/lang/Cloneable",ITest.class.getName().replace('.','/')}); String field="test";
    Object defaultValue=123d;
    String setMd="setTest";
    String getMd="getTest";
    cw.visitField(ACC_PRIVATE,field,"D",null,null).visitEnd(); MethodVisitor mv=cw.visitMethod(ACC_PUBLIC,getMd,"()D",null,null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD,0);
    mv.visitFieldInsn(GETFIELD,className,field,"D");
    mv.visitInsn(DRETURN);
    mv.visitMaxs(0,0);// 自动计算局部变量和栈大小
    mv.visitEnd();
    cw.visitEnd(); mv=cw.visitMethod(ACC_PUBLIC,setMd,"(D)V",null,null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD,0);
    mv.visitVarInsn(DLOAD,1);
    mv.visitFieldInsn(PUTFIELD,className,field,"D");
    mv.visitInsn(RETURN);
    mv.visitMaxs(0,0);// 自动计算
    mv.visitEnd(); // 下面产生构造方法
    mv=cw.visitMethod(ACC_PUBLIC,"<init>","()V",null,null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD,0);
    mv.visitMethodInsn(INVOKESPECIAL,"java/lang/Object","<init>","()V");
    if(defaultValue != null){
    //在构造方法中赋默认值
    mv.visitVarInsn(ALOAD,0);
    mv.visitLdcInsn(Double.parseDouble(defaultValue.toString()));
    mv.visitFieldInsn(PUTFIELD,className,field,"D");
    }
    mv.visitInsn(RETURN);
    mv.visitMaxs(0,0);// 自动计算
    mv.visitEnd(); cw.visitEnd(); byte[] bs=cw.toByteArray();
    // FileUtil.writeFile("d:/test/asm/Example.class",bs); MyCLassLoader loader=new MyCLassLoader();
    Class c=loader.defineClass(bs); c.getConstructor(new Class[0]);
    ITest ins=(ITest)c.newInstance();
    //ins.setTest(100.0d);
    System.out.println(ins.getTest());
    } public interface ITest{
    public double getTest(); public void setTest(double d);
    } public static class MyCLassLoader extends ClassLoader{
    public Class defineClass(byte[] data){
    return super.defineClass(null,data,0,data.length,null);
    }
    }
    }