Make delicious recipes!

Adding annotations dynamically using Javassist byte-code editor


Javassist is a Java byte-code editor which allows to:
  1. Define a new class at runtime
  2. Modify a class file when the JVM loads it
  3. Insert byte-code in the form of source text, which is compiled on the fly by Javassist
  4. Add new methods to classes


Following code shows how to add an annotation dynamically to any field before loading its class:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.prismoskills</groupId>
  <artifactId>javassist-examples</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>javassist-examples</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.18.1-GA</version>
    </dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>


package com.prismoskills.javassist.examples.annotation;

import java.lang.reflect.Field;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;


/**
 * Example showing how to dynamically add an annotation in Java
 */
public class AddingAnnotationDynamically
{
    static String pkgName = "com.prismoskills.javassist.examples.annotation";

    public static void main(String[] args) throws Exception
    {
        ClassPool cp = ClassPool.getDefault();
        CtClass cc = cp.get(pkgName + ".SomeClass");
        // Without the call to "makePackage()", package information is lost
        cp.makePackage(cp.getClassLoader(), pkgName);
        addAnnotation(cc, "someField", "java.lang.Deprecated");
        // Changes are not persisted without a call to "toClass()"
        Class<?> c = cc.toClass();

        Field fld = SomeClass.class.getDeclaredField("someField");
        System.out.println(c.getPackage());
        System.out.println(fld.getAnnotation(Deprecated.class));
    }

    public static void addAnnotation(
            CtClass clazz,
            String fieldName,
            String annotationName) throws Exception
    {
        ClassFile cfile = clazz.getClassFile();
        ConstPool cpool = cfile.getConstPool();
        CtField cfield  = clazz.getField(fieldName);

        AnnotationsAttribute attr =
                new AnnotationsAttribute(cpool, AnnotationsAttribute.visibleTag);
        Annotation annot = new Annotation(annotationName, cpool);
        attr.addAnnotation(annot);
        cfield.getFieldInfo().addAttribute(attr);
    }
}

class SomeClass
{
    SomeClass someField;
}

Output for the above is:
package com.prismoskills.javassist.examples.annotation
@java.lang.Deprecated()










Like us on Facebook to remain in touch
with the latest in technology and tutorials!


Got a thought to share or found a
bug in the code?
We'd love to hear from you:

Name:
Email: (Your email is not shared with anybody)
Comment:

Facebook comments:

Site Owner: Sachin Goyal