@@ -96,21 +96,31 @@ public byte[] injectAnnotation(byte[] originalBytes, ConstantPoolData cpd) {
9696
9797 // Constant pool count
9898 int originalConstantPoolCount = originalBuffer .getShort () & 0xFFFF ;
99- int newConstantPoolCount = originalConstantPoolCount + cpd .entryCount ();
100- dos .writeShort (newConstantPoolCount + 1 ); // we always add one for "RuntimeVisibleAnnotations"
101-
99+
102100 int cpStart = originalBuffer .position ();
103101 skipConstantPool (originalBuffer , originalConstantPoolCount - 1 );
104102 int cpEnd = originalBuffer .position ();
105103
106104 byte [] existingCpData = new byte [cpEnd - cpStart ];
107105 originalBuffer .position (cpStart );
108106 originalBuffer .get (existingCpData );
107+
108+ int rvaUtf8Index = findUtf8InConstantPool (existingCpData , originalConstantPoolCount - 1 , "RuntimeVisibleAnnotations" );
109+ boolean rvaExists = rvaUtf8Index > 0 ;
110+
111+ int newConstantPoolCount = originalConstantPoolCount + cpd .entryCount ();
112+ if (!rvaExists ) {
113+ newConstantPoolCount ++; // add one for "RuntimeVisibleAnnotations"
114+ }
115+ dos .writeShort (newConstantPoolCount );
116+
109117 dos .write (existingCpData );
110118
111119 // new entries
112120 dos .write (cpd .data ());
113- writeUtf8Entry (dos , "RuntimeVisibleAnnotations" );
121+ if (!rvaExists ) {
122+ writeUtf8Entry (dos , "RuntimeVisibleAnnotations" );
123+ }
114124
115125 dos .writeShort (originalBuffer .getShort ()); // access flags
116126 dos .writeShort (originalBuffer .getShort ()); // this_class
@@ -126,7 +136,7 @@ public byte[] injectAnnotation(byte[] originalBytes, ConstantPoolData cpd) {
126136 copyMembers (originalBuffer , dos ); // methods
127137
128138 // Calculate indices for our new entries
129- CPIndices indices = new CPIndices (originalConstantPoolCount );
139+ CPIndices indices = new CPIndices (originalConstantPoolCount , rvaExists ? rvaUtf8Index : - 1 );
130140 // 6. Handle class attributes (add RuntimeVisibleAnnotations)
131141 int classAttrCount = originalBuffer .getShort () & 0xFFFF ;
132142 int rvaIndex = findRuntimeVisibleAnnotationsAttribute (originalBytes , originalBuffer .position () - 2 , classAttrCount );
@@ -351,6 +361,48 @@ private void copyMembers(ByteBuffer buffer, DataOutputStream out) throws IOExcep
351361 }
352362 }
353363
364+ private int findUtf8InConstantPool (byte [] cpData , int cpCount , String target ) {
365+ ByteBuffer buffer = ByteBuffer .wrap (cpData );
366+ int currentIndex = 1 ; // Constant pool indices start at 1
367+
368+ for (int i = 0 ; i < cpCount ; i ++) {
369+ int tag = buffer .get () & 0xFF ;
370+
371+ switch (tag ) {
372+ case 1 : // UTF8
373+ int len = buffer .getShort () & 0xFFFF ;
374+ byte [] utf8Bytes = new byte [len ];
375+ buffer .get (utf8Bytes );
376+ String utf8String = new String (utf8Bytes , java .nio .charset .StandardCharsets .UTF_8 );
377+ if (utf8String .equals (target )) {
378+ return currentIndex ;
379+ }
380+ break ;
381+ case 3 : case 4 : // Integer, Float
382+ buffer .getInt ();
383+ break ;
384+ case 5 : case 6 : // Long, Double
385+ buffer .getLong ();
386+ i ++; // takes 2 slots
387+ currentIndex ++; // Long and Double take 2 constant pool slots
388+ break ;
389+ case 7 : case 8 : case 16 : case 19 : case 20 : // Class, String, etc.
390+ buffer .getShort ();
391+ break ;
392+ case 9 : case 10 : case 11 : case 12 : case 17 : case 18 : // Fieldref, etc.
393+ buffer .getInt ();
394+ break ;
395+ case 15 : // MethodHandle
396+ buffer .get ();
397+ buffer .getShort ();
398+ break ;
399+ }
400+ currentIndex ++;
401+ }
402+
403+ return -1 ; // Not found
404+ }
405+
354406 private void skipConstantPool (ByteBuffer buffer , int count ) {
355407 for (int i = 0 ; i < count ; i ++) {
356408 int tag = buffer .get () & 0xFF ;
@@ -399,7 +451,7 @@ private class CPIndices {
399451 final int isDirectDependencyValueIndex ;
400452 final int rvaNameIndex ;
401453
402- CPIndices (int baseCPCount ) {
454+ CPIndices (int baseCPCount , int existingRvaIndex ) {
403455 int offset = 0 ;
404456
405457 annotationTypeIndex = baseCPCount + offset ++;
@@ -423,7 +475,12 @@ private class CPIndices {
423475 isDirectDependencyNameIndex = baseCPCount + offset ++;
424476 isDirectDependencyValueIndex = baseCPCount + offset ++;
425477
426- rvaNameIndex = baseCPCount + offset ; // This won't exist in cpData!
478+ // Use existing index if found, otherwise calculate new index
479+ if (existingRvaIndex > 0 ) {
480+ rvaNameIndex = existingRvaIndex ;
481+ } else {
482+ rvaNameIndex = baseCPCount + offset ;
483+ }
427484 }
428485 }
429486}
0 commit comments