• Javassist指引(一)


    原文链接

    [TOC]

    1. 读写字节码

    1.1概述

    Javassist是一个Java字节码类库。Java的字节码是包含Java类与接口,并按照一定的顺序存在class文件中。
    Javassist.CtClass一个class文件的抽象表述。一个CtClass(compile-time class)的实例是一个可以用来操作class文件的句柄。下面是一个简单的例子:

    ClassPool pool = ClassPool.getDefault();
    CtClass cc = pool.get("test.Rectangle");
    cc.setSuperclass(pool.get("test.Point"));
    cc.writeFile();
    

    这个程序首先创建了一个ClassPool实例,在Javassist中,ClassPool是用来管理字节码的编辑,ClassPool是一个存放着代表class文件的CtClass类容器,它扫描读取了class文件并且构造了CtClass类,并且是后面响应修改class文件的入口。
    如果想要修改一个class文件,用户必须实例化一个ClassPool类,并且使用ClassPool的get方法取得代表这个那个class文件的CtClass的引用。在上面的例子中,ClassPoll.getDefault()用来代表在默认的路径进行搜索,而cc则是test.Rectangle的CtClass的引用。
    通过观察ClassPool的实现类,我们发现ClassPool是一个存放着CtClass的Hashtable,key是类名。在Javassist中,我们发现,如果这个类不存在,那么将抛出一个NotFoundException。
    在上面的例子中,我们仅仅只是修改了TestRectangle的父类,在第4章,我们将介绍更多修改类的方式。
    当我们使用writeFile()的时候,我们做的修改将会正式生效。writeFile()会把CtClass以class文件的形势写入磁盘。Javassist为哦我们提供将一个类转成bytecode的方法toBytecode():

      byte[] bytes = cc.toBytecode();
    

    也提供了获得一个Java.lang.Class的方法

      Class clazz = cc.toClass();
    

    1.2定义一个新的类

    我们可以通过ClassPoll::makeClass()的方法定义一个新的类。

    ClassPool pool = ClassPool.getDefault();
    CtClass cc = pool.makeClass("Point");
    

    这个程序中定义了一个没有任何成员的Point类。我们可以定义一个CtNewMethod的方法,并通过CtClass::addMethod方法添加到Point类中。
    我们我们需要创建一个interface而非一个class,那么我们可以用ClassPool::makeInterface()的方法。接口的方法我们可以使用CtNewMethod中的abstractMethod()。

    1.3冻结类

    当一个CtClass类用writeFile(), toClass(), toBytecode()生成一个class文件后,Javassist会冻结该CtClass类。如果再对这个类进行修改,会抛出一个RuntimeException。我们可以通过调用defrost()解冻后才能对CtClass进行修改。

    1.4类搜索路径

    当我们调用ClassPool.getDefault()的时候,默认的路径与JVM默认搜索路径相同。当程序运行在JBoss或者Tomcat这种Web容器时,因为它们本身有着多个ClassLoader,所以用上面的方法可能无法获取到类。我们可以通过下面这种形式:

    ClassPool pool = ClassPool.getDefault();
    pool.insertClassPath(new ClassClassPath(this.getClass()));
    

    我们也可以添加一个类的搜索路径,如:

    pool.insertClassPath("/usr/local/javalib")
    

    也可以添加一个URL

    ClassPath cp = new URLClassPath("www.javassist.org", 80, "/java/", "org.javassist.");
    pool.insertClassPath(cp);
    

    另外,如果你知道类的完整路径及名字,我们也可以使用makeClass。

    ClassPool cp = ClassPool.getDefault();
    InputStream ins = an input stream for reading a class file;
    CtClass cc = cp.makeClass(ins);
    

    makeClass会从inputStream中构造出对应的类。当jar包比较大时,对jar包的搜索会消耗性能,这个方法有效地减少了性能消耗。

    原文地址:https://www.jianshu.com/p/abd1c885c341
  • 相关阅读:
    luogu P3704 [SDOI2017]数字表格
    「雅礼集训 2018 Day4」Magic(分治NTT)
    「清华集训 2017」小 Y 和恐怖的奴隶主
    [WC2019]数树(树形dp+多项式exp)
    「FJWC2020Day5-zzq」lg (容斥)
    BoundedOptimization TopCoder
    MapGuessing TopCoder
    线性递推(Berlekamp-Massey 算法)
    杜教筛小记
    「余姚中学 2019 联测 Day 6」解码
  • 原文地址:https://www.cnblogs.com/jpfss/p/11060292.html
Copyright © 2020-2023  润新知