动态创建类:
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.IOException;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.V1_5;
public class CreateClass {
public static void createFakeClass(String builddir) throws IOException {
ClassWriter cw = new ClassWriter(0);
// public, 类名, 父类,接口
cw.visit(V1_5, ACC_PUBLIC, "com/example/autolog/FakeClass", null, "java/lang/Object", null);
ClassVisitor cv = new AddFieldVisitor(Opcodes.ASM5, cw);
//增加一个成员mName
cv.visitField(ACC_PUBLIC, "mName", "Ljava/lang/String;", null, null);
//增加构造方法
cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null).visitCode();
//增加setName方法,参数为String,返回类型为void
cv.visitMethod(ACC_PUBLIC, "setName", "(Ljava/lang/String;)V", null, null).visitCode();
//增加getName方法,无参数,返回类型为String
cv.visitMethod(ACC_PUBLIC, "getName", "()Ljava/lang/String;", null, null).visitCode();
cv.visitEnd();
//拷贝到javac
FileUtils.writeByteArrayToFile(
new File(builddir + "/intermediates/javac/debug/classes/com/example/autolog/FakeClass.class"),
cw.toByteArray());
//将生成类拷贝到transforms,用于dex
FileUtils.writeByteArrayToFile(
new File(builddir + "/intermediates/transforms/auto-log/debug/0/com/example/autolog/FakeClass.class"),
cw.toByteArray());
}
public static class AddFieldVisitor extends ClassVisitor {
public AddFieldVisitor(int api, ClassVisitor cv) {
super(api, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if ("<init>".equals(name)) {
//在构造方法中进行变量初始化
return new InitField(Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions));
} else if ("getName".equals(name)) {
//给getName方法增加字节码
return new GetName(Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions));
} else if ("setName".equals(name)) {
//给setName增加字节码
return new SetName(Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions));
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
class InitField extends MethodVisitor {
public InitField(int api, MethodVisitor cv) {
super(api, cv);
}
@Override
public void visitCode() {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitLdcInsn("haha");
mv.visitFieldInsn(Opcodes.PUTFIELD, "com/example/autolog/FakeClass", "mName", "Ljava/lang/String;");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
}
class GetName extends MethodVisitor {
public GetName(int api, MethodVisitor mv) {
super(api, mv);
}
@Override
public void visitCode() {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, "com/example/autolog/FakeClass", "mName", "Ljava/lang/String;");
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
}
class SetName extends MethodVisitor {
public SetName(int api, MethodVisitor mv) {
super(api, mv);
}
@Override
public void visitCode() {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.PUTFIELD, "com/example/autolog/FakeClass", "mName", "Ljava/lang/String;");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
}
}
}
在Transform中进行创建类
class LogTransform extends Transform {
Project project;
LogTransform(Project project) {
this.project = project
}
@Override
String getName() {
return 'auto-log'
}
@Override
Set<QualifiedContent.ContentType> getInputTypes() {
return TransformManager.CONTENT_CLASS
}
@Override
Set<? super QualifiedContent.Scope> getScopes() {
return TransformManager.PROJECT_ONLY
}
@Override
boolean isIncremental() {
return false
}
@Override
void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
//...
CreateClass.createFakeClass(project.getBuildDir().getAbsolutePath())
}
运行时使用该类
try {
Class fake = Class.forName("com.example.autolog.FakeClass");
Object obj = fake.newInstance();
Method setname = fake.getDeclaredMethod("setName", String.class);
setname.setAccessible(true);
setname.invoke(obj, "mainactivity");
Method getname = fake.getDeclaredMethod("getName");
getname.setAccessible(true);
Log.e("onresume ", "mname : " + getname.invoke(obj));
} catch (Exception e) {
e.printStackTrace();
}
Android中不能在运行时动态创建类:
因为创建类之后,ClassWriter生成的byte[],不能被自定义的ClassLoader加载