search
HomeJavajavaTutorialHow to use Javassist in Java

How to use Javassist in Java

May 17, 2023 pm 08:07 PM
javajavassist

    开篇

    说起 AOP 小伙伴们肯定很熟悉,无论是 JDK 动态代理或者是 CGLIB 等,其底层都是通过操作 Java 字节码来实现代理。ASM、AspectJ和Javassist等是常用的操作字节码的技术。

    ASM 其设计和实现是尽可能小而且快,更专注于性能。它在指令的层面来操作,所以使用它需要对 JVM 的指令有所了解,门槛较高,CGLIB 就使用了 ASM 技术。

    AspectJ 扩展了 Java 语言,定义了一系列 AOP 语法,在 JVM 中运行需要使用特定的编译器生成遵守 Java 字节码规范的 Class 文件,Spring AOP 使用了 AspectJ 。

    Javassist 直接使用 Java 编码的形式操作字节码,简单易上手,性能高于反射,相比于 ASM 稍低。

    Javassist 常用类

    Javassist 抽象出一个 ClassPool 对象来操作 Java 类,可以通过 ClassPool.getDefault() 来获取默认的 ClassPool 。常用的对象:

    CtClass:代表一个 Class 的实例,可以通过类的全限定名来获取 CtClass 对象,其中包含了对 Class 的各种操作。

    ClassPool:通过 HashTable 保存了路径下的 CtClass 信息,key为类的全限定名称,value 为类名对应的 CtClass 对象。

    CtMethod、CtField:抽象出类的方法和属性,可以用于定义或修改方法和字段。

    Javassist 的使用

    依赖

    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.27.0-GA</version>
    </dependency>

    代码示例

    // 获取默认类池
      ClassPool classPool = ClassPool.getDefault();
      // 1. 创建空类
      CtClass ctClass = classPool.makeClass("com.aysaml.demo.javassist.User");
    
      // 2. 创建 String 类型的 name 字段
      CtField field = new CtField(classPool.get("java.lang.String"), "name", ctClass);
      // 设置字段访问级别 private
      field.setModifiers(Modifier.PRIVATE);
      // 增加字段
      ctClass.addField(field);
    
      // 3. 增加 getter & setter 方法
      ctClass.addMethod(CtNewMethod.getter("getName", field));
      ctClass.addMethod(CtNewMethod.setter("setName", field));
    
      // 4. 增加无参构造方法:其中 $0 表示 this,$1 表示参数
      CtConstructor noArgsCons = new CtConstructor(new CtClass[] {}, ctClass);
      noArgsCons.setBody("{$0.name=\"mark\";}");
      ctClass.addConstructor(noArgsCons);
    
      // 5. 增加有参构造方法
      CtConstructor hasArgsCons =
        new CtConstructor(new CtClass[] {classPool.get("java.lang.String")}, ctClass);
      hasArgsCons.setBody("{$0.name=$1;}");
      ctClass.addConstructor(hasArgsCons);
    
      // 6. 创建方法
      CtMethod method = new CtMethod(CtClass.voidType, "printName", new CtClass[] {}, ctClass);
      method.setBody("{System.out.println($0.name);}");
      ctClass.addMethod(method);
    
      // 7. 生成类文件:可指定路径,默认为当前项目根目录
      ctClass.writeFile();
    
      // 8. 创建类实例
      Object person = ctClass.toClass().newInstance();

    如何实现类似 AOP 的功能

    javassist 对于编程化的操作字节码是很简单易懂的,我们以在方法的开头结尾打印信息为例:

    public class Cat {
    
     /** 记录喵喵喵的次数 */
     private int num;
    
     public void miao() {
      this.num++;
     }
    }

    我们要在 miao( ) 方法的前增加声音输出:

    public static void main(String[] args) throws NotFoundException, CannotCompileException {
      ClassPool classPool = ClassPool.getDefault();
      // 获取 Cat 类的 CtClass 对象
      CtClass catClass = classPool.get("com.aysaml.demo.javassist.Cat");
      // 获取 miao( ) 方法
      CtMethod method = catClass.getDeclaredMethod("miao");
      method.insertBefore("System.out.println(\"miao~\");");
      // 加载修改过的类,注意必须要保证调用前这个类没有被加载过
      catClass.toClass();
      //测试
      Cat cat = new Cat();
      cat.miao();
     }

    注意到,在使用 catClass.toClass() 加载被修改过的类时,强调必须保证在调用前这个类没有被加载过,否则会报 attempted duplicate class definition for name 异常。

    我们知道一个类是不能被一个类加载器加载两次的,所以为了解决这个问题,需要制定一个没有加载过该类的 Classloader,Javassist 提供了一个 ClassLoader ,如下:

    public class Cat {
    
     /** 记录喵喵喵的次数 */
     private int num;
    
     public void miao() {
      System.out.println("调用了 miao 方法");
      this.num++;
     }
    
     public static void main(String[] args) throws Exception{
      ClassPool classPool = ClassPool.getDefault();
      // 获取 Cat 类的 CtClass 对象
      CtClass catClass = classPool.get("com.aysaml.demo.javassist.Cat");
      // 获取 miao( ) 方法
      CtMethod method = catClass.getDeclaredMethod("miao");
      method.insertBefore("System.out.println(\"miao~\");");
      // 重新设置一个 Classloader
      Loader classLoader = new Loader(classPool);
      Class clazz = classLoader.loadClass("com.aysaml.demo.javassist.Cat");
      // 调用修改过的类的方法
      clazz.getDeclaredMethod("miao").invoke(clazz.newInstance());
     }
    }

    执行结果为:

    How to use Javassist in Java

    The above is the detailed content of How to use Javassist in Java. For more information, please follow other related articles on the PHP Chinese website!

    Statement
    This article is reproduced at:亿速云. If there is any infringement, please contact admin@php.cn delete
    Why is Java a popular choice for developing cross-platform desktop applications?Why is Java a popular choice for developing cross-platform desktop applications?Apr 25, 2025 am 12:23 AM

    Javaispopularforcross-platformdesktopapplicationsduetoits"WriteOnce,RunAnywhere"philosophy.1)ItusesbytecodethatrunsonanyJVM-equippedplatform.2)LibrarieslikeSwingandJavaFXhelpcreatenative-lookingUIs.3)Itsextensivestandardlibrarysupportscompr

    Discuss situations where writing platform-specific code in Java might be necessary.Discuss situations where writing platform-specific code in Java might be necessary.Apr 25, 2025 am 12:22 AM

    Reasons for writing platform-specific code in Java include access to specific operating system features, interacting with specific hardware, and optimizing performance. 1) Use JNA or JNI to access the Windows registry; 2) Interact with Linux-specific hardware drivers through JNI; 3) Use Metal to optimize gaming performance on macOS through JNI. Nevertheless, writing platform-specific code can affect the portability of the code, increase complexity, and potentially pose performance overhead and security risks.

    What are the future trends in Java development that relate to platform independence?What are the future trends in Java development that relate to platform independence?Apr 25, 2025 am 12:12 AM

    Java will further enhance platform independence through cloud-native applications, multi-platform deployment and cross-language interoperability. 1) Cloud native applications will use GraalVM and Quarkus to increase startup speed. 2) Java will be extended to embedded devices, mobile devices and quantum computers. 3) Through GraalVM, Java will seamlessly integrate with languages ​​such as Python and JavaScript to enhance cross-language interoperability.

    How does the strong typing of Java contribute to platform independence?How does the strong typing of Java contribute to platform independence?Apr 25, 2025 am 12:11 AM

    Java's strong typed system ensures platform independence through type safety, unified type conversion and polymorphism. 1) Type safety performs type checking at compile time to avoid runtime errors; 2) Unified type conversion rules are consistent across all platforms; 3) Polymorphism and interface mechanisms make the code behave consistently on different platforms.

    Explain how Java Native Interface (JNI) can compromise platform independence.Explain how Java Native Interface (JNI) can compromise platform independence.Apr 25, 2025 am 12:07 AM

    JNI will destroy Java's platform independence. 1) JNI requires local libraries for a specific platform, 2) local code needs to be compiled and linked on the target platform, 3) Different versions of the operating system or JVM may require different local library versions, 4) local code may introduce security vulnerabilities or cause program crashes.

    Are there any emerging technologies that threaten or enhance Java's platform independence?Are there any emerging technologies that threaten or enhance Java's platform independence?Apr 24, 2025 am 12:11 AM

    Emerging technologies pose both threats and enhancements to Java's platform independence. 1) Cloud computing and containerization technologies such as Docker enhance Java's platform independence, but need to be optimized to adapt to different cloud environments. 2) WebAssembly compiles Java code through GraalVM, extending its platform independence, but it needs to compete with other languages ​​for performance.

    What are the different implementations of the JVM, and do they all provide the same level of platform independence?What are the different implementations of the JVM, and do they all provide the same level of platform independence?Apr 24, 2025 am 12:10 AM

    Different JVM implementations can provide platform independence, but their performance is slightly different. 1. OracleHotSpot and OpenJDKJVM perform similarly in platform independence, but OpenJDK may require additional configuration. 2. IBMJ9JVM performs optimization on specific operating systems. 3. GraalVM supports multiple languages ​​and requires additional configuration. 4. AzulZingJVM requires specific platform adjustments.

    How does platform independence reduce development costs and time?How does platform independence reduce development costs and time?Apr 24, 2025 am 12:08 AM

    Platform independence reduces development costs and shortens development time by running the same set of code on multiple operating systems. Specifically, it is manifested as: 1. Reduce development time, only one set of code is required; 2. Reduce maintenance costs and unify the testing process; 3. Quick iteration and team collaboration to simplify the deployment process.

    See all articles

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Tools

    WebStorm Mac version

    WebStorm Mac version

    Useful JavaScript development tools

    Safe Exam Browser

    Safe Exam Browser

    Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

    SublimeText3 Linux new version

    SublimeText3 Linux new version

    SublimeText3 Linux latest version

    MantisBT

    MantisBT

    Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)