Hello bcel developers, I’m sorry in advance if I’m writing to a wrong place.
I use bcel to annotate some specific fields and methods in already compiled code. Currently I work on task to migrate from version 6.0 to 6.2. I run into some issues and seek for advice: 1. org.apache.bcel.util.BCELifier does not support runtime annotations for class fields and methods (I did not test class annotations). Should it support them? When debugging I found that i.e. field object in method org.apache.bcel.util.BCELifier#visitField does contain attribute of type org.apache.bcel.classfile.RuntimeVisibleAnnotations and its table is filled appropriately. It seems org.apache.bcel.util.BCELifier#visitField is missing some code for annotation support. Basically same thing applies to org.apache.bcel.util.BCELifier#visitMethod as well. 2. org.apache.bcel.generic.FieldGenOrMethodGen#addAnnotationEntry method is now protected. Should it be deprecated? Seems now correct way to read/write annotations is to use org.apache.bcel.classfile.RuntimeVisibleAnnotations attribute. 3. While trying to implement code that adds runtime annotation to a field I noticed that org.apache.bcel.classfile.RuntimeVisibleAnnotations has a constructor only for reading from input. Should it have one for creating the attribute? I.e. it could provide the second constructor from its superclass: org.apache.bcel.classfile.Annotations#Annotations(byte, int, int, org.apache.bcel.classfile.AnnotationEntry[], org.apache.bcel.classfile.ConstantPool, boolean) to avoid unnecessary complicated implementation on user end. I temporarily solved it by copying org.apache.bcel.classfile.RuntimeVisibleAnnotations class to my source base and providing the appropriate constructor. Also when creating org.apache.bcel.classfile.AnnotationEntry I run into NullPointerException. None of its constructors initialize org.apache.bcel.classfile.AnnotationEntry#element_value_pairs collection, only method org.apache.bcel.classfile.AnnotationEntry#read does. This issue I had to solve via reflection. Should it initialize the collection? Maybe it could be initialized on demand if not already. Here’s a simple fragment of code that adds runtime annotation to a field for the version 6.2: private static void addTestAnnotation(FieldGen field) { ConstantPoolGen cp = field.getConstantPool(); ObjectType objectType = new ObjectType("com.nomagic.tools.ant.annotator.TestAnnotation"); AnnotationEntry annotationEntry = new AnnotationEntry(cp.addUtf8(objectType.getSignature()), cp.getConstantPool(), true); fixUninitializedLists(annotationEntry); SimpleElementValueGen value = new SimpleElementValueGen(ElementValueGen.STRING, cp, "Some test text"); ElementValuePairGen pairGen = new ElementValuePairGen("testMessage", value, cp); annotationEntry.addElementNameValuePair(pairGen.getElementNameValuePair()); AnnotationEntry[] annotation_table = new AnnotationEntry[]{annotationEntry}; int nameIndex = cp.addUtf8(Const.getAttributeName(Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS)); // RuntimeVisibleAnnotations is copy of original class with changed constructor RuntimeVisibleAnnotations runtimeVisibleAnnotations = new RuntimeVisibleAnnotations(nameIndex, annotation_table.length, annotation_table, cp.getConstantPool()); field.addAttribute(runtimeVisibleAnnotations); } private static void fixUninitializedLists(AnnotationEntry annotationEntry) { java.lang.reflect.Field[] fields = annotationEntry.getClass().getDeclaredFields(); for (java.lang.reflect.Field field : fields) { field.setAccessible(true); if(field.getType().equals(List.class)) { try { Object value = field.get(annotationEntry); if (value == null) { field.set(annotationEntry, new ArrayList()); } } catch (Exception e) { e.printStackTrace(); } } } } Maybe org.apache.bcel.generic.FieldGenOrMethodGen class could have a method like addRuntimeVisibleAnnotation(AnnotationEntryGen) and inside it could check if it has special annotations attribute (create if not) and then add annotation to the attribute. Seems like adding annotation to a class field or method is no longer supported. Or maybe implementation is not complete. Or maybe I’m using wrong API. If you need, I can provide sample intellij project. Please let me know what you think about this. Sincerely, -- Tomas Lukosius Software Developer No Magic Europe Savanoriu ave. 363, LT-51480, Kaunas, Lithuania Phone: +370 37 324032, fax: +370 37 320670 E-mail: tomas.lukos...@nomagic.com<mailto:tomas.lukos...@nomagic.com> www.nomagic.com<http://www.nomagic.com/> www.magicdraw.com<http://www.magicdraw.com/> Important change to No Magic e-mail addresses. Following No Magic acquisition by Dassault Systèmes, please use my Dassault Systèmes email address tomas.lukos...@3ds.com<mailto:tomas.lukos...@3ds.com> to contact me. Don't forget to add the new address to your Safe Senders list, to ensure you will continue to receive my e-mails.