asm动态生成类和get and set方法
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.测试结果
测试的时候会在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;
}
}
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);
}
}
}
评论区
请写下您的评论...
猜你喜欢
blog
asm生成for循环语句方法
java基础
2329
asm生成for循环语句方法1.jar包2.原java文件packageclub.jiajia.test3;publicclassExamp4{ publicintmethod(inta
blog
asm生成switch语句方法
java基础
2421
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
springboot,java基础
541
产生原因:文件在进行maven打包后被损坏解决办法通过配置pom.xml过滤不需要maven进行重编码的文件,以下方法选其一即可buildplugins!--资源文件拷贝插件
blog
asm实例对象方法的调用
java基础
2940
asm实例对象方法的调用1.需要的jar包2.我们需要通过asm生成的目标类如下:packageclub.jiajia.test3;publicclassExamp5
blog
关于父类和子类方法发生重载的问题
其他
9314
在一本书上看到过子类可以重载父类的方法,关于这一点有点疑惑,个人重载是发生在同一个类中。网上关于这个也存在争议。先暂时作为一个问题记录在此下面这张图片引用自《疯狂java讲义第三版》关于重写,遵循以
blog
asm类型描述符和方法描述符
java虚拟机(jvm)
5687
1.内部名在许多情况下,一种类型只能是类或接口类型。例如,一个类的超类、由一个类实现的接口,或者由一个方法抛出的异常就不能是基元类型或数组类型,必须是类或接口类型。这些类型在已编译类中用内部名字表示
前端(h5)
2725
定义和用法splice()方法向/从数组中添加/删除项目,然后返回被删除的项目。注意:该方法会改变原始数组。语法arrayObject.splice(index,howmany,item1
前端(h5)
3115
语法:varmap=newMap();属性:size返回集合中元素的数量方法:clear从映射中移除所有元素。delete从映射中移除指定的元素。forEach对映射中的每个元素执行指定操作。get
最新发表
归档
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
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。