asm实例对象方法的调用

硅谷探秘者 3094 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基础 4710 静态不能new内部类解析:我们知道非静态内部类有一个特点就是可以访问外部类非静态属性,而外部类属性只有再创建以后才有,而静态属于类,不属于,所以再main执行
前端(h5) 3203 :varmap=newMap();属性:size返回集合中元素数量:clear从映射中移除所有元素。delete从映射中移除指定元素。forEach映射中每个元素执行指定操作。get
数据结构与算法 1604 java使欧几里得算计算比 publicstaticvoidmain(String[]args){ System.out.println(bili(2,6
框架 1518 能手动去写这些逻辑。最终把它封装成一个可以便直接转换成得工具类。首先明确我们得目是什么现有一个excel表,如下图:现需要把excel表中每一行都封装在一个java中,当然如果poia
前端(h5) 2614 概念浅拷贝只会拷贝一层,如果数组中是,则只会拷贝,如果是基本数据类型则会拷贝值。深拷贝多层次拷贝,如果数组中是,则会连同一起拷贝。concat现浅拷贝vara=[{id:1
算法基础 1219 ]=0; System.out.println(a[0]+""+b[0]); }结果打印是10说明一位数组clone是深拷贝数组b和数组a并不是同一个二位数组clone测试代码public
weblog 919 1.双重检查式特点:线程安全;延迟加载;效率较高,推荐使/*** 双重检查式,线程安全;延迟加载;效率较高。*@authorLENOVO**/publicclassSingleton
java基础 2447 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 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。