`
name327
  • 浏览: 163170 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

asm动态生成class,并且动态加载执行

阅读更多

本人初学,我也搞得不是很明白,目前只做出这个demo, asm那些操作具体是什么意思,请查看asm的api 。

性能方面,没测试

废话不多说了,直接上代码

首先把自定义的类加器搞上来

 

package net;

public class MyClassLoader extends ClassLoader
{
    @SuppressWarnings("unchecked")
    public  Class defineClassByName(String name,byte[] b,int off,int len){ 
        Class clazz = super.defineClass(name,b, off, len);
        return clazz; 
      } 
}
 

 

下面上动态生成class的代码,visit方法的第一个参数为class的版本号,jdk1.6的用49,目前没有找到每个jdk所对应的class文件版本号。

 

package net;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;


public class AsmDemo
{
    @SuppressWarnings("unchecked")
    public static void main(String[] args)
    {
        /*生成类文件的结构,代码现在是这样
         * public class HelloWorld{
         * 
         * }
         */
        ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_MAXS);
        cw.visit(49, Opcodes.ACC_PUBLIC, "HelloWorld", null, "java/lang/Object", null);
        Method m=Method.getMethod("void <init> ()");
        GeneratorAdapter ga=new GeneratorAdapter(Opcodes.ACC_PUBLIC,m,null,null,cw);
        ga.loadThis();
        ga.invokeConstructor(Type.getType(Object.class), m);
        ga.returnValue();
        ga.endMethod();
        /*
         * 在HelloWorld中添加main方法,在main方法中添加代码,代码现在是这样子
         * public class HelloWorld{
         *  public static void mian(String[] args){
         *      System.out.println("Hello World!");
         *  }
         * }
         */
        m = Method.getMethod("void main (String[])");
        ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, m, null, null, cw);
        ga.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
        ga.push("Hello World!");
        ga.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)"));
        ga.returnValue();
        ga.endMethod();
        cw.visitEnd();
        /*
         * 这个方法用于后面的类动态加载测试,HelloWorld中的结构现在已经变成
         * public class HelloWorld{
         *  public static void mian(String[] args){
         *      System.out.println("Hello World!");
         *  }
         *  public void doSomething(){
         *      System.out.println("动态生成,动态加载调用方法");
         *  }
         * }
         */
        m=Method.getMethod("void doSomething()");
        ga=new GeneratorAdapter(Opcodes.ACC_PUBLIC,m,null,null,cw);
        ga.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
        ga.push("动态生成,动态加载调用方法");
        ga.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println(String)"));
        ga.returnValue();
        ga.endMethod();
        
        
        MyClassLoader mcl=new MyClassLoader();
        //利用自定义的类加载器把生成类文件加载到jvm 。
        byte[]  bytes=cw.toByteArray();
        //返回的对象时被加载类的class
        Class hw=mcl.defineClassByName("HelloWorld", bytes, 0, bytes.length);
        try
        {
            //利用反射创建对象
            Object o=hw.newInstance();
            java.lang.reflect.Method method=   o.getClass().getMethod("doSomething");
            method.invoke(o);
            /*把文件生成的class文件写入磁盘 File.separator为文件分隔符(知道的勿喷)
             * ,它会根据操作系统不同,而自动转换,比直接写成\\这种通用性强。
             * 这个路径原来一般写成d:\\HelloWorld.class
             */
            File file=new File("d:"+File.separator+"HelloWorld.class");
            FileOutputStream fos=new FileOutputStream(file);
            fos.write(cw.toByteArray());
            fos.flush();
            fos.close();
        }
        catch (FileNotFoundException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (InstantiationException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (SecurityException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (NoSuchMethodException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IllegalArgumentException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (InvocationTargetException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

 

 运行这个控制台输出为

动态生成,动态加载调用方法

 

然后我们发现d多了个class文件,打开命令提示符切换到d盘,输入java HelloWorld

控制台输出

Hello World!

源码和所需Jar包在附件中

分享到:
评论

相关推荐

    asm 最新版手册

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm4-guide.pdf

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm4.1 jar+demo+doc

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    ASM4中文使用指南.zip

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm-9.0.jar

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm5.0 源码+demo+doc

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm操作指南(中文)

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    ASM4使用指南.

    ASM4使用指南. asm是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。asm可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。

    Java字节码操纵框架 asm-3.1组件包大集合

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm-analysis-3.2.jar

    asm-analysis-3.2.jar 它包含了一个名为`AsmAnalysis`的类,这个...例如,它可以生成二进制的class文件,也可以在类被加载入JVM之前动态修改类行为。此外,ASM库还提供了一些常用的简化字节码生成、转换的类和适配器。

    『ApkTool』APK破解工具

    定为最终版的原因是支持动态加载最新的内置工具: ..\Bin\*.*目录下的所有工具如果有最新版本的,替换Bin目录内的程序即可应用最新版。 [注意:不要更改目录内的文件名,否则不会被加载。],判断是否使用最新版本的...

    byte-buddy-1.9.12.jar

    还有一个名气更大的库mockito,其核心就是基于byte buddy实现的,可以动态生成mock类,非常方便。另外一个大的应用就是 java agent,其主要作用是在class 被加载之前对其拦截,插入自己的代码。

Global site tag (gtag.js) - Google Analytics