Discussion:
[bcel] runtime visible annotation attribute support for class fields and method
Tomas Lukošius
2018-11-05 09:30:12 UTC
Permalink
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: ***@nomagic.com<mailto:***@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 ***@3ds.com<mailto:***@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.
Loading...