Skip to content

Commit 36c8e52

Browse files
authored
perf: remove redundancy of RVA (#78)
1 parent 8e72224 commit 36c8e52

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

classport-commons/src/main/java/io/github/project/classport/commons/AnnotationConstantPool.java

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
-28 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)