asm实例对象方法的调用

硅谷探秘者 1800 0 0

asm实例对象方法的调用


1.需要的jar包


2.我们需要通过asm生成的目标类如下:

package club.jiajia.test3;
public class Examp5 {
	public int method(){
		Abc a=new Abc(1, 2);
		return a.ab();
	}
	
	public int method2(){
		Abc a=new Abc();
		a.b=422;
		a.setA(456);
		return a.ab();
	}
}


3.目标类需要引用的对象是:

package club.jiajia.test3;
public class Abc {
	private int a;
	public int b;
	public Abc(int a,int b){
		this.a=a;
		this.b=b;
	}
	public Abc(){
		
	}
	public int ab(){
		return a+b;
	}
	public int getA(){
		return this.a;
	}
	public void setA(int a){
		this.a=a;
	}
}


4.我们先分析一下目标类的字节码文件:

javap -c命令,反编译一下:

method:stack=4, locals=2, args_size=1

method2:stack=2, locals=2, args_size=1

Compiled from "Examp5.java"
public class club.jiajia.test3.Examp5 {
  public club.jiajia.test3.Examp5();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public int method();
    Code:
       0: new           #16                 // class club/jiajia/test3/Abc	//-创建一个对象,并将其引用值压入栈顶
       3: dup																//-复制栈顶数值并将复制值压入栈顶
       4: iconst_1															//-将int型1推送至栈顶
       5: iconst_2															//-将int型2推送至栈顶
       6: invokespecial #18                 // Method club/jiajia/test3/Abc."<init>":(II)V	//-调用超类构造方法,实例初始化方法,私有方法
       9: astore_1															//- 将栈顶引用型数值存入第二个本地变量  
      10: aload_1															//将第二个引用类型本地变量推送至栈顶
      11: invokevirtual #21                 // Method club/jiajia/test3/Abc.ab:()I	//-调用实例方法 
      14: ireturn		
      
  public int method2();
    Code:
       0: new           #16                 // class club/jiajia/test3/Abc //-创建一个对象,并将其引用值压入栈顶
       3: dup	//-复制栈顶数值并将复制值压入栈顶
       4: invokespecial #27                 // Method club/jiajia/test3/Abc."<init>":()V	//-调用超类构造方法,实例初始化方法,私有方法
       7: astore_1	//- 将栈顶引用型数值存入第二个本地变量  
       8: aload_1	//将第二个引用类型本地变量推送至栈顶
       9: sipush        422	//-将一个短整型常量值(-32768~32767)推送至栈顶
      12: putfield      #28 //为指定的类的实例域赋值  	              // Field club/jiajia/test3/Abc.b:I
      15: aload_1	//将第二个引用类型本地变量推送至栈顶
      16: sipush        456	//-将一个短整型常量值(-32768~32767)推送至栈顶
      19: invokevirtual #32                 // Method club/jiajia/test3/Abc.setA:(I)V	//-调用实例方法 
      22: aload_1	//将第二个引用类型本地变量推送至栈顶
      23: invokevirtual #21                 // Method club/jiajia/test3/Abc.ab:()I	//-调用实例方法 
      26: ireturn	//-从当前方法返回int
}	

5.通过对字节码的分析可以通过asm生成我们想要的类

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.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class TestAsm5 implements Opcodes{
	public static void main(String[] args) throws InstantiationException, IllegalAccessException{
		ClassWriter cw=new ClassWriter(0);
		String className="Example5";
		cw.visit(0x31,ACC_PUBLIC,className,null,"java/lang/Object",new String[]{"java/lang/Cloneable",ITest.class.getName().replace('.','/')});
		String method="method";
		String method2="method2";
		MethodVisitor mv;
		
		/***********************************************************/
		mv=cw.visitMethod(ACC_PUBLIC,method,"()I",null,null);
		mv.visitCode();
		
		mv.visitTypeInsn(NEW,"club/jiajia/test3/Abc");
		mv.visitInsn(DUP);
		mv.visitInsn(ICONST_1);
		mv.visitInsn(ICONST_2);
		mv.visitMethodInsn(INVOKESPECIAL, "club/jiajia/test3/Abc", "<init>","(II)V");
		mv.visitVarInsn(ASTORE,1);
		mv.visitVarInsn(ALOAD,1);
		mv.visitMethodInsn(INVOKEVIRTUAL, "club/jiajia/test3/Abc", "ab", "()I");
		mv.visitInsn(IRETURN);
		mv.visitMaxs(4,2);
		mv.visitEnd();
		
		/*2*******************************************************/
		
		mv=cw.visitMethod(ACC_PUBLIC,method2,"()I",null,null);
		mv.visitCode();
		
		mv.visitTypeInsn(NEW,"club/jiajia/test3/Abc");
		mv.visitInsn(DUP);
		mv.visitMethodInsn(INVOKESPECIAL, "club/jiajia/test3/Abc", "<init>","()V");
		mv.visitVarInsn(ASTORE,1);
		mv.visitVarInsn(ALOAD,1);
		mv.visitIntInsn(SIPUSH,422);
		mv.visitFieldInsn(PUTFIELD, "club/jiajia/test3/Abc","b","I");
		mv.visitVarInsn(ALOAD,1);
		mv.visitIntInsn(SIPUSH,456);
		mv.visitMethodInsn(INVOKEVIRTUAL, "club/jiajia/test3/Abc", "setA", "(I)V");
		mv.visitVarInsn(ALOAD,1);
		mv.visitMethodInsn(INVOKEVIRTUAL, "club/jiajia/test3/Abc", "ab", "()I");
		
		mv.visitInsn(IRETURN);
		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/Example5.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();
		System.out.println(ins.method());
		System.out.println(ins.method2());
	}
	public interface ITest{
		public int method();
		public int method2();
	}
	public static class MyCLassLoader extends ClassLoader{
		public Class<?> defineClass(byte[] data){
			return super.defineClass(null,data,0,data.length,null);
		}
	}
}

6.反编译生成的字节码文件,与我们预计的是完全相同的

asd.jpg


猜你喜欢
java基础 3105 静态不能new内部类解析:我们知道非静态内部类有一个特点就是可以访问外部类非静态属性,而外部类属性只有再创建以后才有,而静态属于类,不属于,所以再main执行
前端(h5) 2237 :varmap=newMap();属性:size返回集合中元素数量:clear从映射中移除所有元素。delete从映射中移除指定元素。forEach映射中每个元素执行指定操作。get
数据结构与算法 438 java使欧几里得算计算比 publicstaticvoidmain(String[]args){ System.out.println(bili(2,6
前端(h5) 1627 概念浅拷贝只会拷贝一层,如果数组中是,则只会拷贝,如果是基本数据类型则会拷贝值。深拷贝多层次拷贝,如果数组中是,则会连同一起拷贝。concat现浅拷贝vara=[{id:1
框架 436 能手动去写这些逻辑。最终把它封装成一个可以便直接转换成得工具类。首先明确我们得目是什么现有一个excel表,如下图:现需要把excel表中每一行都封装在一个java中,当然如果poia
算法基础 270 ]=0; System.out.println(a[0]+""+b[0]); }结果打印是10说明一位数组clone是深拷贝数组b和数组a并不是同一个二位数组clone测试代码public
weblog 188 1.双重检查式特点:线程安全;延迟加载;效率较高,推荐使/*** 双重检查式,线程安全;延迟加载;效率较高。*@authorLENOVO**/publicclassSingleton
java基础 1091 asm生成for循环语句1.jar包2.原java文件packageclub.jiajia.test3;publicclassExamp4{ publicintmethod(inta
归档
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月  5 2020年12月  3 2021年01月  1 2021年02月  5 2021年03月  7 2021年04月  4 2021年05月  4 2021年06月  1 2021年07月  7 2021年08月  2 2021年09月  8 2021年10月  9
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议
目录
祝愿神州十三飞行乘组平安归来