Annotations are a new feature from Java 5. Annotations are a kind of comment or meta data you can insert in your Java code. But how can we add them dynamically at runtime to the java class since the jdk doesn’t provide any addAnnotation method ?
Introduction
Java annotations were introduced in 2002 through the JCP (JSR-175) and were approved inSeptember 2004 as an alternative to the configuration xml files. Java annotations, can (if necessary) be accessible to the programmer at the runtime through reflection api.
Java annotations were introduced in 2002 through the JCP (JSR-175) and were approved inSeptember 2004 as an alternative to the configuration xml files. Java annotations, can (if necessary) be accessible to the programmer at the runtime through reflection api.
How to scan java annotations?
The easiest way to scan through a resource is to load it through a Classloader and use the Java Reflection API to look for the specified annotation. However, this approach will only help you to find annotations that are visible at runtime @Retention (value = RetentionPolicy.RUNTIME), and loading each resource into memory will consume an unnecessary amount of memory.
Lets create a simple annotation, annotations are defined like interfaces. Here is the @PersonneName definition:
package sample; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(value = RetentionPolicy.RUNTIME) //The annotation is saved in the*.class and can be used by the JVM. @Target(value = ElementType.METHOD) //The annotation can be used on methods. public @interface PersonneName { public String name(); }
let's now create a simple SayHelloBean on wich we will apply this simple annotation
package sample; import java.lang.reflect.Method; import sample.PersonneName; public class SayHelloBean { private static final String HELLO_MSG = "Hello "; @PersonneName(name="World !! (simple annotation)") public String sayHelloTo(String name){ return HELLO_MSG+name; } public static void main(String[] args) { try{ //instanciate the bean SayHelloBean simpleBean = new SayHelloBean(); //get the method descriptor through reflection Method helloMessageMethod = simpleBean.getClass().getDeclaredMethod("sayHelloTo", String.class); //scan the annotation PersonneName mySimpleAnnotation = (PersonneName) helloMessageMethod.getAnnotation(PersonneName.class); System.out.println(simpleBean.sayHelloTo(mySimpleAnnotation.name())); } catch(Exception e){ e.printStackTrace(); } } }
Runing the main method produce : Hello World !! (simple annotation)
How to add Annotations dynamically at Runtime to a java class method?
Why ?
- Jdk doesn’t provide an addAnnotation method through reflection.
- Sometimes we need to define annotation dynamically at runtime (example of jsr 303 validation annotations )
- Add new behaviors to your classes
How ?
We will use Javassist (Java Programming Assistant) . It is a class library for editing bytecodes in Java; it enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it. (More informations and downloads here javassist ).
Now let’s modify the preceding example to add the @PersonneName at runtime to the SayHelloBean,first we will delete the annotation from the SayHelloBean code
package sample; public class SayHelloBean { private static final String HELLO_MSG = "Hello "; public String sayHelloTo(String name){ return HELLO_MSG+name; } }
second we create the class AddRunTimeAnnotation that will add the annotation dynamically to the SayHelloBean class :
package sample; import java.lang.reflect.Method; import sample.PersonneName; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.StringMemberValue; public class AddRunTimeAnnotation { public static void addPersonneNameAnnotationToMethod(String className,String methodName) throws Exception{ //pool creation ClassPool pool = ClassPool.getDefault(); //extracting the class CtClass cc = pool.getCtClass(className); //looking for the method to apply the annotation on CtMethod sayHelloMethodDescriptor = cc.getDeclaredMethod(methodName); // create the annotation ClassFile ccFile = cc.getClassFile(); ConstPool constpool = ccFile.getConstPool(); AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag); Annotation annot = new Annotation("sample.PersonneName", constpool); annot.addMemberValue("name", new StringMemberValue("World!! (dynamic annotation)",ccFile.getConstPool())); attr.addAnnotation(annot); // add the annotation to the method descriptor sayHelloMethodDescriptor.getMethodInfo().addAttribute(attr); // transform the ctClass to java class Class dynamiqueBeanClass = cc.toClass(); //instanciating the updated class SayHelloBean sayHelloBean = (SayHelloBean) dynamiqueBeanClass.newInstance(); try{ Method helloMessageMethod = sayHelloBean.getClass().getDeclaredMethod(methodName, String.class); //getting the annotation PersonneName personneName = (PersonneName) helloMessageMethod.getAnnotation(PersonneName.class); System.out.println(sayHelloBean.sayHelloTo(personneName.name())); } catch(Exception e){ e.printStackTrace(); } } public static void main(String[] args) { try { AddRunTimeAnnotation.addPersonneNameAnnotationToMethod("sample.SayHelloBean", "sayHelloTo"); } catch (Exception e) { e.printStackTrace(); } } }Runing the main method now produce : Hello World!! (dynamic annotation).
Looking ahead
There's a lot more to Javassist than what we've covered in this article. Javassist enables Java programs to define a new class at runtime and to modify a class file before the JVM loads it. Unlike other similar systems, Javassist provides source-level abstraction; programmers can modify a class file without detailed knowledge of the Java bytecode.start enjoying it :).
Ressources :
Great article with great examples ! i think it would be better to explain more How to implement this ...
ReplyDeletethanks for sharing your code
ReplyDeletethanks ,it helped me .
ReplyDeletehi,
ReplyDeleteI am getting following error while executing "Class dynamiqueBeanClass = cc.toClass();"
Error:
javassist.CannotCompileException: by java.lang.LinkageError attempted duplicate class definition for name
Please help me out.
Thanks
Hi and sorry for my late response :
ReplyDeleteThe JVM does not allow dynamically reloading a class. Thus, you cannot alter the definition of a class after the JVM loads it. However if you want to do so you have to create your own classloader because in java, multiple class loaders can coexist and each class loader creates its own name space check this :
http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html#load
Hi there,
ReplyDeleteHave following -
jvm arguments -Xmx512m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
private static final String hotSwapPort = "8000";
...
HotSwapper hotSwapper = new HotSwapper(hotSwapPort);
byte[] classBytes = ctClass.toBytecode();
hotSwapper.reload(className, classBytes);
But end up getting the following error -
java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
I am able to connect to the port via eclipse remote debug and have no firewall.
Any insights would be helpful.
Thanks in advance.
very good article.. thanks for sharing
ReplyDeleteAww. This is awesome. Thank you!
ReplyDeleteThis will be awesome... if works...
ReplyDeletejavassist.CannotCompileException: by java.lang.LinkageError attempted duplicate class definition for name
I want to add the annotation to the Class instead the method, what should i done after
ReplyDeleteCtClass cc = pool.getCtClass(className);
Did you figure it out?
DeleteI am getting following error while executing "Class dynamiqueBeanClass = cc.toClass();"
ReplyDeleteError:
javassist.CannotCompileException: by java.lang.LinkageError attempted duplicate class definition for name
Please help me out.
Hi,
ReplyDeleteThanks for sharing of your article you are given a valuable information. Java programming was released by sun micro-system.
I love reading through your blog and look forward to all your posts! Keep up the great work!
ReplyDeleteบาคาร่า
จีคลับ
gclub
มาเล่น”สล็อต” กันดีกว่า
ReplyDeleteเนื่องจากเป็นการเล่นพนันที่ใช้เงินลงทุนน้อย แต่มีโอกาสชนะเดิมพันที่มีทั้งรางวัลเล็กและรางวัลใหญ่ได้เงินเป็นจำนวนมาก ได้ลุ้นระทึก สร้างความเร้าใจตลอดช่วงเวลาที่วงล้อของสล็อตหมุนไป ปัจจุบันปัจจุบันเทคโนโลยีสื่อสารที่ทันสมัย ทำให้ เกมส์สล็อต ได้รับการพัฒนาและยกระดับ จากที่เคยเล่นกันแพร่หลายเฉพาะในสถาน ให้สามารถเล่นกันทางออนไลน์ได้แล้ว
โดยการเล่นผ่านเว็บไซต์ผู้ให้บริการ ออนไลน์ หรือแอพริเคชั่นบนมือถือ ซึ่งการเล่น เกมสล็อตออนไลน์ ได้รับความนิยมไม่ยิ่งหย่อนไปกว่าการเล่นสล็อตในสถาน หรืออาจจะได้ว่าได้รับความนิยมมากกว่าในสถานก็ว่าได้ เนื่องจากอำนวยสะดวกให้แก่ผู้ที่ชื่นชอบการเล่นสล็อตสามารถเล่นได้ทุกที่ ทุกเวลา ไม่พลาดโอกาสการทำกำไรได้ทั้งวันทั่งคืน ปัจจุบันสล็อตออนไลน์ เป็นหนึ่งในเกมส์พนันออนไลน์ที่ได้รับความนิยมสูงมาก
สล็อต
Thanks for taking the time to discuss this, I feel strongly about it and love learning more on this topic.
ReplyDeleteJava代写
Great Blog post very useful info thanks for this post ....
ReplyDeletepower bi training chennai |Power bi training class chennai
https://www.blogger.com/comment.g?blogID=8417362&postID=5012066968442970822&page=1&token=1580798459827&isPopup=true
ReplyDeleteThank you for the useful educational article
ReplyDeleteSa gaming
ReplyDeleteI would like to show you about my blog.
สูตรบาคาร่า สูตรบาคาร่า
สูตรบาคาร่า
OMG! This is a very great blog.
ReplyDeleteสูตรบาคาร่า สูตรบาคาร่า สูตรบาคาร่า
How to write great blogs.
ReplyDeleteสูตรบาคาร่า สูตรบาคาร่า สูตรบาคาร่า สูตรบาคาร่า
Excellent blog, I wish to share your post with my folks circle. It’s really helped me a lot, so keep sharing post like this
ReplyDeleteDevOps Training in Chennai
DevOps Course in Chennai
Respect and that i have a nifty offer you: Renovation House Company updating exterior of home
ReplyDelete