asm实例对象方法的调用
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.反编译生成的字节码文件,与我们预计的是完全相同的
猜你喜欢
java基础
3632
静态方法不能new内部类的实例对象解析:我们知道非静态内部类有一个特点就是可以访问外部类对象的非静态属性,而外部类的的属性只有再创建对象以后才有,而静态方法属于类,不属于对象,所以再main方法执行
前端(h5)
2701
语法:varmap=newMap();属性:size返回集合中元素的数量方法:clear从映射中移除所有元素。delete从映射中移除指定的元素。forEach对映射中的每个元素执行指定操作。get
blog
java使用欧几里得算法计算比例的方法
数据结构与算法
1018
java使用欧几里得算法计算比例的方法 publicstaticvoidmain(String[]args){ System.out.println(bili(2,6
前端(h5)
2104
概念浅拷贝只会拷贝一层,如果数组中是对象,则只会拷贝对象引用,如果是基本数据类型则会拷贝值。深拷贝多层次拷贝,如果数组中是对象,则会连同对象一起拷贝。concat方法实现浅拷贝vara=[{id:1
框架
1015
能手动去写这些逻辑。最终把它封装成一个可以方便直接转换成对象得工具类。首先明确我们得目的是什么现有一个excel表,如下图:现需要把excel表中的每一行都封装在一个java对象中,当然如果用poi的a
算法基础
752
]=0;
System.out.println(a[0]+""+b[0]);
}结果打印的是10说明一位数组的clone方法是深拷贝数组b和数组a并不是同一个对象二位数组的clone方法测试代码public
ofc
单例模式的5种实现方法-设计模式
weblog
592
1.双重检查的方式特点:线程安全;延迟加载;效率较高,推荐使用/*** 双重检查的方式,线程安全;延迟加载;效率较高。*@authorLENOVO**/publicclassSingleton
blog
asm生成for循环语句方法
java基础
1815
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
标签
算法基础
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
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。