asm动态生成类和get and set方法

硅谷探秘者 1964 0 0

asm动态生成类和get and set方法

1.自定义类加载器

package club.jiajia.test;
public class MyClassLoader extends ClassLoader{  
    public  Class<?> defineClassByName(String name,byte[] b,int off,int len){   
        Class<?> clazz = super.defineClass(name,b, off, len);  
        return clazz;   
    }   
}

2.asm动态生成字节码

package club.jiajia.test2;
import java.util.List;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
/**
 * jiajiajia
 */
public class Asm implements Opcodes {
    public byte[] createBeanClass(String className, List<FieldInfo> fields) {
        ClassWriter cw = new ClassWriter(0);
        cw.visit(V1_1, ACC_PUBLIC, className, null, "java/lang/Object", null);
        // creates a MethodWriter for the (implicit) constructor
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(RETURN);
        mv.visitMaxs(1, 1);
 
        for (FieldInfo f : fields) {
            addMethod(cw, mv, className, f);
        }
 
        return cw.toByteArray();
    }
 
    private void addMethod(ClassWriter cw, MethodVisitor mv, String className,
                                  FieldInfo fieldInfo) {
        String fieldName = fieldInfo.name;
        String setMethodName = "set" +fieldName;
        String getMethodName = "get" +fieldName;
 
        String typeof = Type.getType(fieldInfo.type).getDescriptor();
        String getof = getof(typeof);
        String setof = setof(typeof);
        int[] loadAndReturnOf = loadAndReturnOf(typeof);
        
        //add field
        cw.visitField(ACC_PRIVATE, fieldName, typeof, null, 0).visitEnd();
 
        // getMethod
        mv = cw.visitMethod(ACC_PUBLIC, getMethodName, getof, null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, className, fieldName, typeof);
        mv.visitInsn(loadAndReturnOf[1]);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
        
        // setMethod
        mv = cw.visitMethod(ACC_PUBLIC, setMethodName, setof, null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(loadAndReturnOf[0], 1);
        mv.visitFieldInsn(PUTFIELD, className, fieldName, typeof);
        mv.visitInsn(RETURN);
        mv.visitMaxs(3, 3);
        mv.visitEnd();
    }
 
    private String setof(String typeof) {
        return "(" + typeof + ")V";
    }
 
    private String getof(String typeof) {
        return "()" + typeof;
    }
    private int[] loadAndReturnOf(String typeof) {
        if (typeof.equals("I") || typeof.equals("Z")) {
            return new int[]{ILOAD,IRETURN};
        } else if (typeof.equals("J")) {
            return new int[]{LLOAD,LRETURN};
        } else if (typeof.equals("D")) {
            return new int[]{DLOAD,DRETURN};
        } else if (typeof.equals("F")) {
            return new int[]{FLOAD,FRETURN};
        } else {
            return new int[]{ALOAD,ARETURN};
        }
    }
}

3.定义属性信息

package club.jiajia.test2;

public class FieldInfo {
	public Class<?> clazz;
	public String name;
	public String type;
	public Object value;
	public FieldInfo(Class<?> clazz, String name, Object value) {
		super();
		this.clazz = clazz;
		this.name = name;
		this.value = value;
	}
}

4.测试

package club.jiajia.test2;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import club.jiajia.test.MyClassLoader;
 
/**
 * jiajiajia
 */
public class Test extends ClassLoader {
    private static String className="Abc";
    private static List<FieldInfo> fields;
 
    public static byte[] setUp(){
        FieldInfo testString = new FieldInfo(int.class, "name", 1);
        testString.type="I";
        fields = new ArrayList<FieldInfo>();
        fields.add(testString);
        return  new Asm().createBeanClass(className, fields);
    }
    
    public static void main(String[] args) {
		byte b[]=setUp();
		MyClassLoader mcl=new MyClassLoader();  
        //返回的对象时被加载类的class  
        Class<?> hw=mcl.defineClassByName("Abc", b, 0, b.length);  
        try {  
            //利用反射创建对象  
            Object o= hw.newInstance();
            java.lang.reflect.Method method=   o.getClass().getMethod("getname");
            java.lang.reflect.Method method2=   o.getClass().getMethod("setname",int.class);
            method2.invoke(o,3);
            System.out.println(method.invoke(o));
        }catch (Exception e) {
        	e.printStackTrace();
		}
	    
		File file = new File("E://jiajiajia/Abc.class");
		try {
			FileOutputStream fout = new FileOutputStream(file);
			fout.write(b);
			fout.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


5.测试结果

QQ截图20190305161048.png


测试的时候会在E://jiajiajia文件夹下生成一个Abc.clss文件

6.反编译结果为:

public class Abc
{
    private int name = 0;
    
    public int getname() {
        return this.name;
    }
    
    public void setname(final int name) {
        this.name = name;
    }
}








7.测试2

    生成if条件判断

package club.jiajia.test3;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
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";
		String a="a";
		Object defaultValue=123d;
		Object defaultValues=1123;
		String setMd="setTest";
		String getMd="getTest";
		
		String getMa="getMa";
		cw.visitField(ACC_PRIVATE,field,"D",null,defaultValue == null?null:Double.parseDouble(defaultValue.toString())).visitEnd();
		cw.visitField(ACC_PRIVATE,a,"I",null,defaultValues == null?null:Double.parseDouble(defaultValues.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);
		/**
		 * 访问本地变量指令。本地变量指令是ar *指令,它加载或存储本地变量* @param的值。这个操作码是ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE或RET.* @param vanthe操作数的指令访问。这个操作数是一个局部变量的索引
		 */
		mv.visitVarInsn(DLOAD,1);
		mv.visitFieldInsn(PUTFIELD,className,field,"D");
		mv.visitInsn(RETURN);
		mv.visitMaxs(3,3);
		mv.visitEnd();
		
		
		
		
		/***********************************************************/
		mv=cw.visitMethod(ACC_PUBLIC,getMa,"(I)V",null,null);
		mv.visitCode();
		mv.visitVarInsn(ILOAD, 1);
		Label label = new Label();
		mv.visitJumpInsn(IFLT, label);
		mv.visitVarInsn(ALOAD, 0);
		mv.visitVarInsn(ILOAD, 1);
		mv.visitFieldInsn(PUTFIELD, className, "a", "I");
		Label end = new Label();
		mv.visitJumpInsn(GOTO, end);
		mv.visitLabel(label);
		mv.visitFrame(F_SAME, 0, null, 0, null);
		mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
		mv.visitInsn(DUP);
		mv.visitMethodInsn(INVOKESPECIAL,
		"java/lang/IllegalArgumentException", "<init>", "()V");
		mv.visitInsn(ATHROW);
		mv.visitLabel(end);
		mv.visitFrame(F_SAME, 0, null, 0, null);
		mv.visitInsn(RETURN);
		mv.visitMaxs(2, 2);
		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();
		File file = new File("E://jiajiajia/Example.class");
		try {
			FileOutputStream fout = new FileOutputStream(file);
			fout.write(bs);
			fout.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		MyCLassLoader loader=new MyCLassLoader();
		Class<?> c=loader.defineClass(bs);
		
		ITest ins=(ITest)c.newInstance();
		ins.setTest(100.0d);
		ins.getMa(-2);
		System.out.println(ins.getTest());
	}
	
	public interface ITest{
		public double getTest();
		public void setTest(double d);
		public void getMa(int a);
	}

	public static class MyCLassLoader extends ClassLoader{
		public Class defineClass(byte[] data){
			return super.defineClass(null,data,0,data.length,null);
		}
	}
}

反编译结果为

import club.jiajia.test3.*;

public class Example implements Cloneable, TestAsm$ITest
{
    private double test = 123.0;
    private int a = 1123;
    
    public double getTest() {
        return this.test;
    }
    
    public void setTest(final double test) {
        this.test = test;
    }
    
    public void getMa(final int i) {
        while (i < 0) {}
        this.a = i;
    }
}

image.png




8.生成更为复杂的方法

package club.jiajia.test3;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class TestAsm2 implements Opcodes{
	public static void main(String[] args) throws InstantiationException, IllegalAccessException{
		ClassWriter cw=new ClassWriter(0);
		String className="Example2";
		cw.visit(0x31,ACC_PUBLIC,className,null,"java/lang/Object",new String[]{"java/lang/Cloneable",ITest.class.getName().replace('.','/')});

		String a="a";
		Object av=123;
		
		String getA="getA";
		String setA="setA";
		cw.visitField(ACC_PRIVATE,a,"I",null,av == null?null:Integer.parseInt(av.toString())).visitEnd();

		
		MethodVisitor mv=cw.visitMethod(ACC_PUBLIC,getA,"()I",null,null);
		mv.visitCode();
		mv.visitVarInsn(ALOAD,0);
		mv.visitFieldInsn(GETFIELD,className,a,"I");
		mv.visitInsn(IRETURN);
		mv.visitMaxs(2,2);
		mv.visitEnd();
		cw.visitEnd();
		
		
		/***********************************************************/
		mv=cw.visitMethod(ACC_PUBLIC,setA,"(II)V",null,null);
		mv.visitCode();
		mv.visitVarInsn(ILOAD, 1);
		mv.visitVarInsn(ILOAD, 2);
		Label label = new Label();
		mv.visitJumpInsn(IF_ICMPLT, label);
		mv.visitVarInsn(ALOAD, 0);
		mv.visitVarInsn(ILOAD, 1);
		mv.visitFieldInsn(PUTFIELD, className, "a", "I");
		
		Label end = new Label();
		mv.visitJumpInsn(GOTO, end);
		mv.visitLabel(label);
		mv.visitFrame(F_SAME, 0, null, 0, null);
		
		mv.visitVarInsn(ALOAD, 0);
		mv.visitVarInsn(ILOAD, 2);
		mv.visitFieldInsn(PUTFIELD, className, "a", "I");
		
		mv.visitLabel(end);
		mv.visitFrame(F_SAME, 0, null, 0, null);
		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();
		File file = new File("E://jiajiajia/Example2.class");
		try {
			FileOutputStream fout = new FileOutputStream(file);
			fout.write(bs);
			fout.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		MyCLassLoader loader=new MyCLassLoader();
		Class<?> c=loader.defineClass(bs);
		
		ITest ins=(ITest)c.newInstance();
		ins.setA(145,12);
		System.out.println(ins.getA());
	}
	
	public interface ITest{
		public int getA();
		public void setA(int a,int b);
	}

	public static class MyCLassLoader extends ClassLoader{
		public Class<?> defineClass(byte[] data){
			return super.defineClass(null,data,0,data.length,null);
		}
	}
}

menu.saveimg.savepath20190322094711.jpg


猜你喜欢
java基础 730 asmfor循环语句1.jar包2.原java文件packageclub.jiajia.test3;publicclassExamp4{ publicintmethod(inta
java基础 1042 1.jar包:2.原java文件:packageclub.jiajia.test3;publicclassExamp3{ publicintmethod(inta){ switch(a){ case123: a=1230; break; case128: a=1280; break; case12: a=120; break; } returna
java基础 1536 asm实例对象的调用1.需要的jar包2.我们需要通过asm的目标如下:packageclub.jiajia.test3;publicclassExamp5
其他 8267 在一本书上看到过子可以重载父,关于这一点有点疑惑,个人重载是发在同一个中。网上关于这个也存在争议。先暂时作为一个问题记录在此下面这张图片引用自《疯狂java讲义第三版》关于重写,遵循以
java虚拟机(jvm) 3983 1.内部名在许多情况下,一种型只能是或接口型。例如,一个的超、由一个实现的接口,或者由一个抛出的异常就不能是基元型或数组型,必须是或接口型。这些型在已编译中用内部名字表示
前端(h5) 1777 定义splice()向/从数组中添加/删除项目,然后返回被删除的项目。注意:该会改变原始数组。语arrayObject.splice(index,howmany,item1
前端(h5) 2033 :varmap=newMap();属性:size返回集合中元素的数量:clear从映射中移除所有元素。delete从映射中移除指定的元素。forEach对映射中的每个元素执行指定操作。get
java基础 188 1.关于Calendar的set()延迟修改set(f,value)将日历字段f更改为value,此外它还设置了一个内部员变量,以指示日历字段f已经被更改。尽管日历字段f是立即更改的,但是
归档
2018年11月  12 2018年12月  33 2019年01月  28 2019年02月  28 2019年03月  32 2019年04月  27 2019年05月  33 2019年06月  6 2019年07月  12 2019年08月  12 2019年09月  21 2019年10月  8 2019年11月  15 2019年12月  25 2020年01月  9 2020年02月  5 2020年03月  16 2020年04月  4 2020年06月  1 2020年07月  7 2020年08月  13 2020年09月  9 2020年10月  4
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git undefined undefined sdf sdf dsdf sdfasdfasd sdf ppp sdf fggdgsd kkk kkk kkk sdddf 456
目录