【背景】
在正式学习asm时,大家需要对class字节码的格式,语法有一定了解。
根据手册上面的例子,然后生成一个类,再读取一个类进行:
package TestCase;
import org.objectweb.asm.*;
import java.io.*;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 13-8-6
* Time: 上午10:01
* To change this template use File | Settings | File Templates.
*/
public class testProxy
{
public static void main(String[] args){
try{
File f_input=new File("d:/test.class") ;
FileInputStream f_is=new FileInputStream(f_input);
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
byte[] b_1=new byte[1024];
int theRead=f_is.read(b_1);
while (theRead!=-1){
byteArrayOutputStream.write(b_1,0,theRead);
theRead=f_is.read(b_1);
}
f_is.close();
ClassReader creader=new ClassReader(byteArrayOutputStream.toByteArray());
ClassPrinter cp=new ClassPrinter();
creader.accept(cp,0);
ClassWriter cwriter=new ClassWriter(0) ;
cwriter.visit(Opcodes.V1_7,Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT+Opcodes.ACC_INTERFACE,"tmp/test",null,"java/lang/Object",null);
cwriter.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,"attribute_1","I",null,new Integer(-1)).visitEnd();
cwriter.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,"attribute_2","Ljava/lang/String;",null,"").visitEnd();
cwriter.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,"attr_obj","Ljava/lang/String;",null,"").visitEnd();
cwriter.visitMethod(Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT,"compareTo","(Ljava/lang/Object;)I",null,null).visitEnd();
cwriter.visitEnd();
byte[] bytes=cwriter.toByteArray();
File f3=new File("d:/test.class");
if(f3.exists()==false){
f3.createNewFile();
}
FileOutputStream fileOutputStream=new FileOutputStream(f3);
fileOutputStream.write(bytes);
fileOutputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
public static class ClassPrinter extends ClassVisitor{
public ClassPrinter(){
super(Opcodes.ASM4);
}
@Override
public void visit(int version, int access, String name, String signature, String supername, String[] interfaces) {
System.out.println("当前类:版本号:【"+version+"】,名称:【"+name+"】,签名:【"+signature+"】,父类:【"+supername+"】,接口如下:");
if(interfaces!=null){
for (String tmp1:interfaces){
System.out.print("【"+tmp1+"】");
}
System.out.println();
}
System.out.println("class "+name+" extends "+supername+"{");
}
@Override
public void visitSource(String source, String debug) {
}
@Override
public void visitOuterClass(String owner, String name, String desc) {
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return null;
}
@Override
public void visitAttribute(Attribute attr) {
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
System.out.println(" "+desc+" "+name);
return null;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
System.out.println(" "+name+" "+desc);
return null;
}
@Override
public void visitEnd() {
System.out.println("}");
}
}
}
生成自定义类以后如何加载到jvm上面?继承classloader,利用里面的defineClass来加载字节码,下面有一个例子:
public static class myClassLoader1 extends ClassLoader{
public Class LoadDefineClass(String name,byte[] byteCodes,int offset,int len){
return this.defineClass(name,byteCodes,offset,len);
}
}