1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.pack200;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Comparator;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29
30 import org.apache.commons.compress.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
31 import org.apache.commons.compress.harmony.pack200.IcBands.IcTuple;
32 import org.objectweb.asm.Label;
33 import org.objectweb.asm.Opcodes;
34
35
36
37
38 public class ClassBands extends BandSet {
39
40 private static final class TempParamAnnotation {
41
42 int numParams;
43 int[] annoN;
44 IntList pairN = new IntList();
45 List<String> typeRS = new ArrayList<>();
46 List<String> nameRU = new ArrayList<>();
47 List<String> tags = new ArrayList<>();
48 List<Object> values = new ArrayList<>();
49 List<Integer> caseArrayN = new ArrayList<>();
50 List<String> nestTypeRS = new ArrayList<>();
51 List<String> nestNameRU = new ArrayList<>();
52 List<Integer> nestPairN = new ArrayList<>();
53
54 TempParamAnnotation(final int numParams) {
55 this.numParams = numParams;
56 annoN = new int[numParams];
57 }
58
59 void addParameterAnnotation(final int parameter, final String desc, final List<String> nameRU, final List<String> tags,
60 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
61 final List<Integer> nestPairN) {
62 annoN[parameter]++;
63 typeRS.add(desc);
64 pairN.add(nameRU.size());
65 this.nameRU.addAll(nameRU);
66 this.tags.addAll(tags);
67 this.values.addAll(values);
68 this.caseArrayN.addAll(caseArrayN);
69 this.nestTypeRS.addAll(nestTypeRS);
70 this.nestNameRU.addAll(nestNameRU);
71 this.nestPairN.addAll(nestPairN);
72 }
73 }
74
75 private static final long[] EMPTY_LONG_ARRAY = {};
76
77 protected static int countArgs(final String descriptor) {
78 final int bra = descriptor.indexOf('(');
79 final int ket = descriptor.indexOf(')');
80 if (bra == -1 || ket == -1 || ket < bra) {
81 throw new IllegalArgumentException("No arguments");
82 }
83
84 boolean inType = false;
85 boolean consumingNextType = false;
86 int count = 0;
87 for (int i = bra + 1; i < ket; i++) {
88 final char charAt = descriptor.charAt(i);
89 if (inType && charAt == ';') {
90 inType = false;
91 consumingNextType = false;
92 } else if (!inType && charAt == 'L') {
93 inType = true;
94 count++;
95 } else if (charAt == '[') {
96 consumingNextType = true;
97 } else if (inType) {
98
99 } else if (consumingNextType) {
100 count++;
101 consumingNextType = false;
102 } else if (charAt == 'D' || charAt == 'J') {
103 count += 2;
104 } else {
105 count++;
106 }
107 }
108 return count;
109 }
110
111 private final CpBands cpBands;
112 private final AttributeDefinitionBands attrBands;
113 private final CPClass[] class_this;
114 private final CPClass[] class_super;
115
116 private final CPClass[][] class_interface;
117
118 private final int[] class_interface_count;
119 private final int[] major_versions;
120 private final long[] class_flags;
121 private int[] class_attr_calls;
122 private final List<CPUTF8> classSourceFile = new ArrayList<>();
123 private final List<ConstantPoolEntry> classEnclosingMethodClass = new ArrayList<>();
124
125 private final List<ConstantPoolEntry> classEnclosingMethodDesc = new ArrayList<>();
126 private final List<CPSignature> classSignature = new ArrayList<>();
127
128 private final IntList classFileVersionMinor = new IntList();
129 private final IntList classFileVersionMajor = new IntList();
130 private final int[] class_field_count;
131 private final CPNameAndType[][] field_descr;
132 private final long[][] field_flags;
133 private int[] field_attr_calls;
134
135 private final List<CPConstant<?>> fieldConstantValueKQ = new ArrayList<>();
136 private final List<CPSignature> fieldSignature = new ArrayList<>();
137 private final int[] class_method_count;
138 private final CPNameAndType[][] method_descr;
139 private final long[][] method_flags;
140 private int[] method_attr_calls;
141 private final List<CPSignature> methodSignature = new ArrayList<>();
142
143 private final IntList methodExceptionNumber = new IntList();
144 private final List<CPClass> methodExceptionClasses = new ArrayList<>();
145 private int[] codeHeaders;
146 private final IntList codeMaxStack = new IntList();
147 private final IntList codeMaxLocals = new IntList();
148 private final IntList codeHandlerCount = new IntList();
149 private final List codeHandlerStartP = new ArrayList();
150 private final List codeHandlerEndPO = new ArrayList();
151 private final List codeHandlerCatchPO = new ArrayList();
152 private final List<CPClass> codeHandlerClass = new ArrayList<>();
153 private final List<Long> codeFlags = new ArrayList<>();
154 private int[] code_attr_calls;
155 private final IntList codeLineNumberTableN = new IntList();
156 private final List codeLineNumberTableBciP = new ArrayList();
157 private final IntList codeLineNumberTableLine = new IntList();
158 private final IntList codeLocalVariableTableN = new IntList();
159 private final List codeLocalVariableTableBciP = new ArrayList();
160 private final List codeLocalVariableTableSpanO = new ArrayList();
161 private final List<ConstantPoolEntry> codeLocalVariableTableNameRU = new ArrayList<>();
162 private final List<ConstantPoolEntry> codeLocalVariableTableTypeRS = new ArrayList<>();
163 private final IntList codeLocalVariableTableSlot = new IntList();
164 private final IntList codeLocalVariableTypeTableN = new IntList();
165 private final List codeLocalVariableTypeTableBciP = new ArrayList();
166 private final List codeLocalVariableTypeTableSpanO = new ArrayList();
167 private final List<ConstantPoolEntry> codeLocalVariableTypeTableNameRU = new ArrayList<>();
168
169 private final List<ConstantPoolEntry> codeLocalVariableTypeTableTypeRS = new ArrayList<>();
170 private final IntList codeLocalVariableTypeTableSlot = new IntList();
171 private final MetadataBandGroup class_RVA_bands;
172 private final MetadataBandGroup class_RIA_bands;
173 private final MetadataBandGroup field_RVA_bands;
174 private final MetadataBandGroup field_RIA_bands;
175 private final MetadataBandGroup method_RVA_bands;
176 private final MetadataBandGroup method_RIA_bands;
177 private final MetadataBandGroup method_RVPA_bands;
178
179 private final MetadataBandGroup method_RIPA_bands;
180 private final MetadataBandGroup method_AD_bands;
181 private final List<NewAttributeBands> classAttributeBands = new ArrayList<>();
182 private final List<NewAttributeBands> methodAttributeBands = new ArrayList<>();
183
184 private final List<NewAttributeBands> fieldAttributeBands = new ArrayList<>();
185 private final List<NewAttributeBands> codeAttributeBands = new ArrayList<>();
186 private final List<Long> tempFieldFlags = new ArrayList<>();
187 private final List<CPNameAndType> tempFieldDesc = new ArrayList<>();
188 private final List<Long> tempMethodFlags = new ArrayList<>();
189 private final List<CPNameAndType> tempMethodDesc = new ArrayList<>();
190
191 private TempParamAnnotation tempMethodRVPA;
192 private TempParamAnnotation tempMethodRIPA;
193 private boolean anySyntheticClasses;
194 private boolean anySyntheticFields;
195
196 private boolean anySyntheticMethods;
197 private final Segment segment;
198
199 private final Map<CPClass, Set<CPClass>> classReferencesInnerClass = new HashMap<>();
200
201 private final boolean stripDebug;
202 private int index;
203 private int numMethodArgs;
204 private int[] class_InnerClasses_N;
205 private CPClass[] class_InnerClasses_RC;
206 private int[] class_InnerClasses_F;
207
208 private List<CPClass> classInnerClassesOuterRCN;
209
210 private List<CPUTF8> classInnerClassesNameRUN;
211
212 public ClassBands(final Segment segment, final int numClasses, final int effort, final boolean stripDebug) throws IOException {
213 super(effort, segment.getSegmentHeader());
214 this.stripDebug = stripDebug;
215 this.segment = segment;
216 this.cpBands = segment.getCpBands();
217 this.attrBands = segment.getAttrBands();
218 class_this = new CPClass[numClasses];
219 class_super = new CPClass[numClasses];
220 class_interface_count = new int[numClasses];
221 class_interface = new CPClass[numClasses][];
222 class_field_count = new int[numClasses];
223 class_method_count = new int[numClasses];
224 field_descr = new CPNameAndType[numClasses][];
225 field_flags = new long[numClasses][];
226 method_descr = new CPNameAndType[numClasses][];
227 method_flags = new long[numClasses][];
228 for (int i = 0; i < numClasses; i++) {
229 field_flags[i] = EMPTY_LONG_ARRAY;
230 method_flags[i] = EMPTY_LONG_ARRAY;
231 }
232
233 major_versions = new int[numClasses];
234 class_flags = new long[numClasses];
235
236 class_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
237 class_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
238 field_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
239 field_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
240 method_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
241 method_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
242 method_RVPA_bands = new MetadataBandGroup("RVPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
243 method_RIPA_bands = new MetadataBandGroup("RIPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
244 method_AD_bands = new MetadataBandGroup("AD", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
245
246 createNewAttributeBands();
247 }
248
249 public void addAnnotation(final int context, final String desc, final boolean visible, final List<String> nameRU, final List<String> tags,
250 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
251 final List<Integer> nestPairN) {
252 switch (context) {
253 case MetadataBandGroup.CONTEXT_CLASS:
254 if (visible) {
255 class_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
256 if ((class_flags[index] & 1 << 21) != 0) {
257 class_RVA_bands.incrementAnnoN();
258 } else {
259 class_RVA_bands.newEntryInAnnoN();
260 class_flags[index] = class_flags[index] | 1 << 21;
261 }
262 } else {
263 class_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
264 if ((class_flags[index] & 1 << 22) != 0) {
265 class_RIA_bands.incrementAnnoN();
266 } else {
267 class_RIA_bands.newEntryInAnnoN();
268 class_flags[index] = class_flags[index] | 1 << 22;
269 }
270 }
271 break;
272 case MetadataBandGroup.CONTEXT_FIELD:
273 if (visible) {
274 field_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
275 final Long flag = tempFieldFlags.remove(tempFieldFlags.size() - 1);
276 if ((flag.intValue() & 1 << 21) != 0) {
277 field_RVA_bands.incrementAnnoN();
278 } else {
279 field_RVA_bands.newEntryInAnnoN();
280 }
281 tempFieldFlags.add(Long.valueOf(flag.intValue() | 1 << 21));
282 } else {
283 field_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
284 final Long flag = tempFieldFlags.remove(tempFieldFlags.size() - 1);
285 if ((flag.intValue() & 1 << 22) != 0) {
286 field_RIA_bands.incrementAnnoN();
287 } else {
288 field_RIA_bands.newEntryInAnnoN();
289 }
290 tempFieldFlags.add(Long.valueOf(flag.intValue() | 1 << 22));
291 }
292 break;
293 case MetadataBandGroup.CONTEXT_METHOD:
294 if (visible) {
295 method_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
296 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
297 if ((flag.intValue() & 1 << 21) != 0) {
298 method_RVA_bands.incrementAnnoN();
299 } else {
300 method_RVA_bands.newEntryInAnnoN();
301 }
302 tempMethodFlags.add(Long.valueOf(flag.intValue() | 1 << 21));
303 } else {
304 method_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
305 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
306 if ((flag.intValue() & 1 << 22) != 0) {
307 method_RIA_bands.incrementAnnoN();
308 } else {
309 method_RIA_bands.newEntryInAnnoN();
310 }
311 tempMethodFlags.add(Long.valueOf(flag.intValue() | 1 << 22));
312 }
313 break;
314 }
315 }
316
317 public void addAnnotationDefault(final List<String> nameRU, final List<String> tags, final List<Object> values, final List<Integer> caseArrayN,
318 final List<String> nestTypeRS, final List<String> nestNameRU, final List<Integer> nestPairN) {
319 method_AD_bands.addAnnotation(null, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
320 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
321 tempMethodFlags.add(Long.valueOf(flag.longValue() | 1 << 25));
322 }
323
324 public void addClass(final int major, final int flags, final String className, final String signature, final String superName, final String[] interfaces) {
325 class_this[index] = cpBands.getCPClass(className);
326 class_super[index] = cpBands.getCPClass(superName);
327 class_interface_count[index] = interfaces.length;
328 class_interface[index] = new CPClass[interfaces.length];
329 Arrays.setAll(class_interface[index], i -> cpBands.getCPClass(interfaces[i]));
330 major_versions[index] = major;
331 class_flags[index] = flags;
332 if (!anySyntheticClasses && (flags & 1 << 12) != 0 && segment.getCurrentClassReader().hasSyntheticAttributes()) {
333 cpBands.addCPUtf8("Synthetic");
334 anySyntheticClasses = true;
335 }
336
337
338
339
340 if (signature != null) {
341 class_flags[index] |= 1 << 19;
342 classSignature.add(cpBands.getCPSignature(signature));
343 }
344 }
345
346 public void addClassAttribute(final NewAttribute attribute) {
347
348 final String attributeName = attribute.type;
349 for (final NewAttributeBands bands : classAttributeBands) {
350 if (bands.getAttributeName().equals(attributeName)) {
351 bands.addAttribute(attribute);
352 final int flagIndex = bands.getFlagIndex();
353 class_flags[index] |= 1 << flagIndex;
354 return;
355 }
356 }
357 throw new IllegalArgumentException("No suitable definition for " + attributeName);
358 }
359
360 public void addCode() {
361 codeHandlerCount.add(0);
362 if (!stripDebug) {
363 codeFlags.add(Long.valueOf(1 << 2));
364 codeLocalVariableTableN.add(0);
365 }
366 }
367
368 public void addCodeAttribute(final NewAttribute attribute) {
369 final String attributeName = attribute.type;
370 for (final NewAttributeBands bands : codeAttributeBands) {
371 if (bands.getAttributeName().equals(attributeName)) {
372 bands.addAttribute(attribute);
373 final int flagIndex = bands.getFlagIndex();
374 final Long flags = codeFlags.remove(codeFlags.size() - 1);
375 codeFlags.add(Long.valueOf(flags.longValue() | 1 << flagIndex));
376 return;
377 }
378 }
379 throw new IllegalArgumentException("No suitable definition for " + attributeName);
380 }
381
382 public void addEnclosingMethod(final String owner, final String name, final String desc) {
383 class_flags[index] |= 1 << 18;
384 classEnclosingMethodClass.add(cpBands.getCPClass(owner));
385 classEnclosingMethodDesc.add(name == null ? null : cpBands.getCPNameAndType(name, desc));
386 }
387
388 public void addField(int flags, final String name, final String desc, final String signature, final Object value) {
389 flags &= 0xFFFF;
390 tempFieldDesc.add(cpBands.getCPNameAndType(name, desc));
391 if (signature != null) {
392 fieldSignature.add(cpBands.getCPSignature(signature));
393 flags |= 1 << 19;
394 }
395 if ((flags & Opcodes.ACC_DEPRECATED) != 0) {
396 flags &= ~Opcodes.ACC_DEPRECATED;
397 flags |= 1 << 20;
398 }
399 if (value != null) {
400 fieldConstantValueKQ.add(cpBands.getConstant(value));
401 flags |= 1 << 17;
402 }
403 if (!anySyntheticFields && (flags & 1 << 12) != 0 && segment.getCurrentClassReader().hasSyntheticAttributes()) {
404 cpBands.addCPUtf8("Synthetic");
405 anySyntheticFields = true;
406 }
407 tempFieldFlags.add(Long.valueOf(flags));
408 }
409
410 public void addFieldAttribute(final NewAttribute attribute) {
411 final String attributeName = attribute.type;
412 for (final NewAttributeBands bands : fieldAttributeBands) {
413 if (bands.getAttributeName().equals(attributeName)) {
414 bands.addAttribute(attribute);
415 final int flagIndex = bands.getFlagIndex();
416 final Long flags = tempFieldFlags.remove(tempFieldFlags.size() - 1);
417 tempFieldFlags.add(Long.valueOf(flags.longValue() | 1 << flagIndex));
418 return;
419 }
420 }
421 throw new IllegalArgumentException("No suitable definition for " + attributeName);
422 }
423
424 public void addHandler(final Label start, final Label end, final Label handler, final String type) {
425 final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
426 codeHandlerCount.add(handlers + 1);
427 codeHandlerStartP.add(start);
428 codeHandlerEndPO.add(end);
429 codeHandlerCatchPO.add(handler);
430 codeHandlerClass.add(type == null ? null : cpBands.getCPClass(type));
431 }
432
433 public void addLineNumber(final int line, final Label start) {
434 final Long latestCodeFlag = codeFlags.get(codeFlags.size() - 1);
435 if ((latestCodeFlag.intValue() & 1 << 1) == 0) {
436 codeFlags.remove(codeFlags.size() - 1);
437 codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | 1 << 1));
438 codeLineNumberTableN.add(1);
439 } else {
440 codeLineNumberTableN.increment(codeLineNumberTableN.size() - 1);
441 }
442 codeLineNumberTableLine.add(line);
443 codeLineNumberTableBciP.add(start);
444 }
445
446 public void addLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int indx) {
447 if (signature != null) {
448 final Long latestCodeFlag = codeFlags.get(codeFlags.size() - 1);
449 if ((latestCodeFlag.intValue() & 1 << 3) == 0) {
450 codeFlags.remove(codeFlags.size() - 1);
451 codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | 1 << 3));
452 codeLocalVariableTypeTableN.add(1);
453 } else {
454 codeLocalVariableTypeTableN.increment(codeLocalVariableTypeTableN.size() - 1);
455 }
456 codeLocalVariableTypeTableBciP.add(start);
457 codeLocalVariableTypeTableSpanO.add(end);
458 codeLocalVariableTypeTableNameRU.add(cpBands.getCPUtf8(name));
459 codeLocalVariableTypeTableTypeRS.add(cpBands.getCPSignature(signature));
460 codeLocalVariableTypeTableSlot.add(indx);
461 }
462
463 codeLocalVariableTableN.increment(codeLocalVariableTableN.size() - 1);
464 codeLocalVariableTableBciP.add(start);
465 codeLocalVariableTableSpanO.add(end);
466 codeLocalVariableTableNameRU.add(cpBands.getCPUtf8(name));
467 codeLocalVariableTableTypeRS.add(cpBands.getCPSignature(desc));
468 codeLocalVariableTableSlot.add(indx);
469 }
470
471 public void addMaxStack(final int maxStack, int maxLocals) {
472 final Long latestFlag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
473 final Long newFlag = Long.valueOf(latestFlag.intValue() | 1 << 17);
474 tempMethodFlags.add(newFlag);
475 codeMaxStack.add(maxStack);
476 if ((newFlag.longValue() & 1 << 3) == 0) {
477 maxLocals--;
478 }
479 maxLocals -= numMethodArgs;
480 codeMaxLocals.add(maxLocals);
481 }
482
483 public void addMethod(int flags, final String name, final String desc, final String signature, final String[] exceptions) {
484 final CPNameAndType nt = cpBands.getCPNameAndType(name, desc);
485 tempMethodDesc.add(nt);
486 if (signature != null) {
487 methodSignature.add(cpBands.getCPSignature(signature));
488 flags |= 1 << 19;
489 }
490 if (exceptions != null) {
491 methodExceptionNumber.add(exceptions.length);
492 for (final String exception : exceptions) {
493 methodExceptionClasses.add(cpBands.getCPClass(exception));
494 }
495 flags |= 1 << 18;
496 }
497 if ((flags & Opcodes.ACC_DEPRECATED) != 0) {
498 flags &= ~Opcodes.ACC_DEPRECATED;
499 flags |= 1 << 20;
500 }
501 tempMethodFlags.add(Long.valueOf(flags));
502 numMethodArgs = countArgs(desc);
503 if (!anySyntheticMethods && (flags & 1 << 12) != 0 && segment.getCurrentClassReader().hasSyntheticAttributes()) {
504 cpBands.addCPUtf8("Synthetic");
505 anySyntheticMethods = true;
506 }
507 }
508
509 public void addMethodAttribute(final NewAttribute attribute) {
510 final String attributeName = attribute.type;
511 for (final NewAttributeBands bands : methodAttributeBands) {
512 if (bands.getAttributeName().equals(attributeName)) {
513 bands.addAttribute(attribute);
514 final int flagIndex = bands.getFlagIndex();
515 final Long flags = tempMethodFlags.remove(tempMethodFlags.size() - 1);
516 tempMethodFlags.add(Long.valueOf(flags.longValue() | 1 << flagIndex));
517 return;
518 }
519 }
520 throw new IllegalArgumentException("No suitable definition for " + attributeName);
521 }
522
523 public void addParameterAnnotation(final int parameter, final String desc, final boolean visible, final List<String> nameRU, final List<String> tags,
524 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
525 final List<Integer> nestPairN) {
526 if (visible) {
527 if (tempMethodRVPA == null) {
528 tempMethodRVPA = new TempParamAnnotation(numMethodArgs);
529 tempMethodRVPA.addParameterAnnotation(parameter, desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
530 }
531 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
532 tempMethodFlags.add(Long.valueOf(flag.longValue() | 1 << 23));
533 } else {
534 if (tempMethodRIPA == null) {
535 tempMethodRIPA = new TempParamAnnotation(numMethodArgs);
536 tempMethodRIPA.addParameterAnnotation(parameter, desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
537 }
538 final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
539 tempMethodFlags.add(Long.valueOf(flag.longValue() | 1 << 24));
540 }
541 }
542
543 public void addSourceFile(final String source) {
544 String implicitSourceFileName = class_this[index].toString();
545 if (implicitSourceFileName.indexOf('$') != -1) {
546 implicitSourceFileName = implicitSourceFileName.substring(0, implicitSourceFileName.indexOf('$'));
547 }
548 implicitSourceFileName = implicitSourceFileName.substring(implicitSourceFileName.lastIndexOf('/') + 1) + ".java";
549 if (source.equals(implicitSourceFileName)) {
550 classSourceFile.add(null);
551 } else {
552 classSourceFile.add(cpBands.getCPUtf8(source));
553 }
554 class_flags[index] |= 1 << 17;
555 }
556
557 private void createNewAttributeBands() throws IOException {
558 for (final AttributeDefinition def : attrBands.getClassAttributeLayouts()) {
559 classAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
560 }
561 for (final AttributeDefinition def : attrBands.getMethodAttributeLayouts()) {
562 methodAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
563 }
564 for (final AttributeDefinition def : attrBands.getFieldAttributeLayouts()) {
565 fieldAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
566 }
567 for (final AttributeDefinition def : attrBands.getCodeAttributeLayouts()) {
568 codeAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
569 }
570 }
571
572 public void currentClassReferencesInnerClass(final CPClass inner) {
573 if (!(index >= class_this.length)) {
574 final CPClass currentClass = class_this[index];
575 if (currentClass != null && !currentClass.equals(inner) && !isInnerClassOf(currentClass.toString(), inner)) {
576 classReferencesInnerClass.computeIfAbsent(currentClass, c -> new HashSet<>()).add(inner);
577 }
578 }
579 }
580
581 public void doBciRenumbering(final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
582 renumberBci(codeLineNumberTableBciP, bciRenumbering, labelsToOffsets);
583 renumberBci(codeLocalVariableTableBciP, bciRenumbering, labelsToOffsets);
584 renumberOffsetBci(codeLocalVariableTableBciP, codeLocalVariableTableSpanO, bciRenumbering, labelsToOffsets);
585 renumberBci(codeLocalVariableTypeTableBciP, bciRenumbering, labelsToOffsets);
586 renumberOffsetBci(codeLocalVariableTypeTableBciP, codeLocalVariableTypeTableSpanO, bciRenumbering, labelsToOffsets);
587 renumberBci(codeHandlerStartP, bciRenumbering, labelsToOffsets);
588 renumberOffsetBci(codeHandlerStartP, codeHandlerEndPO, bciRenumbering, labelsToOffsets);
589 renumberDoubleOffsetBci(codeHandlerStartP, codeHandlerEndPO, codeHandlerCatchPO, bciRenumbering, labelsToOffsets);
590
591 for (final NewAttributeBands newAttributeBandSet : classAttributeBands) {
592 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
593 }
594 for (final NewAttributeBands newAttributeBandSet : methodAttributeBands) {
595 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
596 }
597 for (final NewAttributeBands newAttributeBandSet : fieldAttributeBands) {
598 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
599 }
600 for (final NewAttributeBands newAttributeBandSet : codeAttributeBands) {
601 newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
602 }
603 }
604
605 public void endOfClass() {
606
607 final int numFields = tempFieldDesc.size();
608 class_field_count[index] = numFields;
609 field_descr[index] = new CPNameAndType[numFields];
610 field_flags[index] = new long[numFields];
611 for (int i = 0; i < numFields; i++) {
612 field_descr[index][i] = tempFieldDesc.get(i);
613 field_flags[index][i] = tempFieldFlags.get(i).longValue();
614 }
615 final int numMethods = tempMethodDesc.size();
616 class_method_count[index] = numMethods;
617 method_descr[index] = new CPNameAndType[numMethods];
618 method_flags[index] = new long[numMethods];
619 for (int i = 0; i < numMethods; i++) {
620 method_descr[index][i] = tempMethodDesc.get(i);
621 method_flags[index][i] = tempMethodFlags.get(i).longValue();
622 }
623 tempFieldDesc.clear();
624 tempFieldFlags.clear();
625 tempMethodDesc.clear();
626 tempMethodFlags.clear();
627 index++;
628 }
629
630 public void endOfMethod() {
631 if (tempMethodRVPA != null) {
632 method_RVPA_bands.addParameterAnnotation(tempMethodRVPA.numParams, tempMethodRVPA.annoN, tempMethodRVPA.pairN, tempMethodRVPA.typeRS,
633 tempMethodRVPA.nameRU, tempMethodRVPA.tags, tempMethodRVPA.values, tempMethodRVPA.caseArrayN, tempMethodRVPA.nestTypeRS,
634 tempMethodRVPA.nestNameRU, tempMethodRVPA.nestPairN);
635 tempMethodRVPA = null;
636 }
637 if (tempMethodRIPA != null) {
638 method_RIPA_bands.addParameterAnnotation(tempMethodRIPA.numParams, tempMethodRIPA.annoN, tempMethodRIPA.pairN, tempMethodRIPA.typeRS,
639 tempMethodRIPA.nameRU, tempMethodRIPA.tags, tempMethodRIPA.values, tempMethodRIPA.caseArrayN, tempMethodRIPA.nestTypeRS,
640 tempMethodRIPA.nestNameRU, tempMethodRIPA.nestPairN);
641 tempMethodRIPA = null;
642 }
643 if (codeFlags.size() > 0) {
644 final long latestCodeFlag = codeFlags.get(codeFlags.size() - 1).longValue();
645 final int latestLocalVariableTableN = codeLocalVariableTableN.get(codeLocalVariableTableN.size() - 1);
646 if (latestCodeFlag == 1 << 2 && latestLocalVariableTableN == 0) {
647 codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
648 codeFlags.remove(codeFlags.size() - 1);
649 codeFlags.add(Long.valueOf(0));
650 }
651 }
652 }
653
654
655
656
657
658 public void finaliseBands() {
659 final int defaultMajorVersion = segmentHeader.getDefaultMajorVersion();
660 for (int i = 0; i < class_flags.length; i++) {
661 final int major = major_versions[i];
662 if (major != defaultMajorVersion) {
663 class_flags[i] |= 1 << 24;
664 classFileVersionMajor.add(major);
665 classFileVersionMinor.add(0);
666 }
667 }
668
669 codeHeaders = new int[codeHandlerCount.size()];
670 int removed = 0;
671 for (int i = 0; i < codeHeaders.length; i++) {
672 final int numHandlers = codeHandlerCount.get(i - removed);
673 final int maxLocals = codeMaxLocals.get(i - removed);
674 final int maxStack = codeMaxStack.get(i - removed);
675 switch (numHandlers) {
676 case 0: {
677 final int header = maxLocals * 12 + maxStack + 1;
678 if (header < 145 && maxStack < 12) {
679 codeHeaders[i] = header;
680 }
681 break;
682 }
683 case 1: {
684 final int header = maxLocals * 8 + maxStack + 145;
685 if (header < 209 && maxStack < 8) {
686 codeHeaders[i] = header;
687 }
688 break;
689 }
690 case 2: {
691 final int header = maxLocals * 7 + maxStack + 209;
692 if (header < 256 && maxStack < 7) {
693 codeHeaders[i] = header;
694 }
695 break;
696 }
697 default:
698 break;
699 }
700 if (codeHeaders[i] != 0) {
701
702
703 codeHandlerCount.remove(i - removed);
704 codeMaxLocals.remove(i - removed);
705 codeMaxStack.remove(i - removed);
706 removed++;
707 } else if (!segment.getSegmentHeader().have_all_code_flags()) {
708 codeFlags.add(Long.valueOf(0));
709 }
710 }
711
712
713 final IntList innerClassesN = new IntList();
714 final List<IcTuple> icLocal = new ArrayList<>();
715 for (int i = 0; i < class_this.length; i++) {
716 final CPClass cpClass = class_this[i];
717 final Set<CPClass> referencedInnerClasses = classReferencesInnerClass.get(cpClass);
718 if (referencedInnerClasses != null) {
719 int innerN = 0;
720 final List<IcTuple> innerClasses = segment.getIcBands().getInnerClassesForOuter(cpClass.toString());
721 if (innerClasses != null) {
722 for (final IcTuple element : innerClasses) {
723 referencedInnerClasses.remove(element.C);
724 }
725 }
726 for (final CPClass inner : referencedInnerClasses) {
727 final IcTuple icTuple = segment.getIcBands().getIcTuple(inner);
728 if (icTuple != null && !icTuple.isAnonymous()) {
729
730 icLocal.add(icTuple);
731 innerN++;
732 }
733 }
734 if (innerN != 0) {
735 innerClassesN.add(innerN);
736 class_flags[i] |= 1 << 23;
737 }
738 }
739 }
740 class_InnerClasses_N = innerClassesN.toArray();
741 class_InnerClasses_RC = new CPClass[icLocal.size()];
742 class_InnerClasses_F = new int[icLocal.size()];
743 classInnerClassesOuterRCN = new ArrayList<>();
744 classInnerClassesNameRUN = new ArrayList<>();
745 for (int i = 0; i < class_InnerClasses_RC.length; i++) {
746 final IcTuple icTuple = icLocal.get(i);
747 class_InnerClasses_RC[i] = icTuple.C;
748 if (icTuple.C2 == null && icTuple.N == null) {
749 class_InnerClasses_F[i] = 0;
750 } else {
751 if (icTuple.F == 0) {
752 class_InnerClasses_F[i] = 0x00010000;
753 } else {
754 class_InnerClasses_F[i] = icTuple.F;
755 }
756 classInnerClassesOuterRCN.add(icTuple.C2);
757 classInnerClassesNameRUN.add(icTuple.N);
758 }
759 }
760
761 final IntList classAttrCalls = new IntList();
762 final IntList fieldAttrCalls = new IntList();
763 final IntList methodAttrCalls = new IntList();
764 final IntList codeAttrCalls = new IntList();
765
766 if (class_RVA_bands.hasContent()) {
767 classAttrCalls.add(class_RVA_bands.numBackwardsCalls());
768 }
769 if (class_RIA_bands.hasContent()) {
770 classAttrCalls.add(class_RIA_bands.numBackwardsCalls());
771 }
772 if (field_RVA_bands.hasContent()) {
773 fieldAttrCalls.add(field_RVA_bands.numBackwardsCalls());
774 }
775 if (field_RIA_bands.hasContent()) {
776 fieldAttrCalls.add(field_RIA_bands.numBackwardsCalls());
777 }
778 if (method_RVA_bands.hasContent()) {
779 methodAttrCalls.add(method_RVA_bands.numBackwardsCalls());
780 }
781 if (method_RIA_bands.hasContent()) {
782 methodAttrCalls.add(method_RIA_bands.numBackwardsCalls());
783 }
784 if (method_RVPA_bands.hasContent()) {
785 methodAttrCalls.add(method_RVPA_bands.numBackwardsCalls());
786 }
787 if (method_RIPA_bands.hasContent()) {
788 methodAttrCalls.add(method_RIPA_bands.numBackwardsCalls());
789 }
790 if (method_AD_bands.hasContent()) {
791 methodAttrCalls.add(method_AD_bands.numBackwardsCalls());
792 }
793
794
795 final Comparator<NewAttributeBands> comparator = (arg0, arg1) -> arg0.getFlagIndex() - arg1.getFlagIndex();
796 classAttributeBands.sort(comparator);
797 methodAttributeBands.sort(comparator);
798 fieldAttributeBands.sort(comparator);
799 codeAttributeBands.sort(comparator);
800
801 for (final NewAttributeBands bands : classAttributeBands) {
802 if (bands.isUsedAtLeastOnce()) {
803 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
804 classAttrCalls.add(backwardsCallCount);
805 }
806 }
807 }
808 for (final NewAttributeBands bands : methodAttributeBands) {
809 if (bands.isUsedAtLeastOnce()) {
810 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
811 methodAttrCalls.add(backwardsCallCount);
812 }
813 }
814 }
815 for (final NewAttributeBands bands : fieldAttributeBands) {
816 if (bands.isUsedAtLeastOnce()) {
817 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
818 fieldAttrCalls.add(backwardsCallCount);
819 }
820 }
821 }
822 for (final NewAttributeBands bands : codeAttributeBands) {
823 if (bands.isUsedAtLeastOnce()) {
824 for (final int backwardsCallCount : bands.numBackwardsCalls()) {
825 codeAttrCalls.add(backwardsCallCount);
826 }
827 }
828 }
829
830 class_attr_calls = classAttrCalls.toArray();
831 field_attr_calls = fieldAttrCalls.toArray();
832 method_attr_calls = methodAttrCalls.toArray();
833 code_attr_calls = codeAttrCalls.toArray();
834 }
835
836 private int[] getInts(final CPClass[] cpClasses) {
837 final int[] ints = new int[cpClasses.length];
838 for (int i = 0; i < ints.length; i++) {
839 if (cpClasses[i] != null) {
840 ints[i] = cpClasses[i].getIndex();
841 }
842 }
843 return ints;
844 }
845
846 public boolean isAnySyntheticClasses() {
847 return anySyntheticClasses;
848 }
849
850 public boolean isAnySyntheticFields() {
851 return anySyntheticFields;
852 }
853
854 public boolean isAnySyntheticMethods() {
855 return anySyntheticMethods;
856 }
857
858 private boolean isInnerClass(final String possibleInner) {
859 return possibleInner.indexOf('$') != -1;
860 }
861
862 private boolean isInnerClassOf(final String possibleInner, final CPClass possibleOuter) {
863 if (isInnerClass(possibleInner)) {
864 final String superClassName = possibleInner.substring(0, possibleInner.lastIndexOf('$'));
865 if (superClassName.equals(possibleOuter.toString())) {
866 return true;
867 }
868 return isInnerClassOf(superClassName, possibleOuter);
869 }
870 return false;
871 }
872
873 public int numClassesProcessed() {
874 return index;
875 }
876
877 @Override
878 public void pack(final OutputStream out) throws IOException, Pack200Exception {
879 PackingUtils.log("Writing class bands...");
880
881 byte[] encodedBand = encodeBandInt("class_this", getInts(class_this), Codec.DELTA5);
882 out.write(encodedBand);
883 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_this[" + class_this.length + "]");
884
885 encodedBand = encodeBandInt("class_super", getInts(class_super), Codec.DELTA5);
886 out.write(encodedBand);
887 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_super[" + class_super.length + "]");
888
889 encodedBand = encodeBandInt("class_interface_count", class_interface_count, Codec.DELTA5);
890 out.write(encodedBand);
891 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface_count[" + class_interface_count.length + "]");
892
893 final int totalInterfaces = sum(class_interface_count);
894 final int[] classInterface = new int[totalInterfaces];
895 int k = 0;
896 for (final CPClass[] element : class_interface) {
897 if (element != null) {
898 for (final CPClass cpClass : element) {
899 classInterface[k] = cpClass.getIndex();
900 k++;
901 }
902 }
903 }
904
905 encodedBand = encodeBandInt("class_interface", classInterface, Codec.DELTA5);
906 out.write(encodedBand);
907 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface[" + classInterface.length + "]");
908
909 encodedBand = encodeBandInt("class_field_count", class_field_count, Codec.DELTA5);
910 out.write(encodedBand);
911 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_field_count[" + class_field_count.length + "]");
912
913 encodedBand = encodeBandInt("class_method_count", class_method_count, Codec.DELTA5);
914 out.write(encodedBand);
915 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_method_count[" + class_method_count.length + "]");
916
917 final int totalFields = sum(class_field_count);
918 final int[] fieldDescr = new int[totalFields];
919 k = 0;
920 for (int i = 0; i < index; i++) {
921 for (int j = 0; j < field_descr[i].length; j++) {
922 final CPNameAndType descr = field_descr[i][j];
923 fieldDescr[k] = descr.getIndex();
924 k++;
925 }
926 }
927
928 encodedBand = encodeBandInt("field_descr", fieldDescr, Codec.DELTA5);
929 out.write(encodedBand);
930 PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_descr[" + fieldDescr.length + "]");
931
932 writeFieldAttributeBands(out);
933
934 final int totalMethods = sum(class_method_count);
935 final int[] methodDescr = new int[totalMethods];
936 k = 0;
937 for (int i = 0; i < index; i++) {
938 for (int j = 0; j < method_descr[i].length; j++) {
939 final CPNameAndType descr = method_descr[i][j];
940 methodDescr[k] = descr.getIndex();
941 k++;
942 }
943 }
944
945 encodedBand = encodeBandInt("method_descr", methodDescr, Codec.MDELTA5);
946 out.write(encodedBand);
947 PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_descr[" + methodDescr.length + "]");
948
949 writeMethodAttributeBands(out);
950 writeClassAttributeBands(out);
951 writeCodeBands(out);
952 }
953
954
955
956
957 public void removeCurrentClass() {
958
959
960 if ((class_flags[index] & 1 << 17) != 0) {
961 classSourceFile.remove(classSourceFile.size() - 1);
962 }
963 if ((class_flags[index] & 1 << 18) != 0) {
964 classEnclosingMethodClass.remove(classEnclosingMethodClass.size() - 1);
965 classEnclosingMethodDesc.remove(classEnclosingMethodDesc.size() - 1);
966 }
967 if ((class_flags[index] & 1 << 19) != 0) {
968 classSignature.remove(classSignature.size() - 1);
969 }
970 if ((class_flags[index] & 1 << 21) != 0) {
971 class_RVA_bands.removeLatest();
972 }
973 if ((class_flags[index] & 1 << 22) != 0) {
974 class_RIA_bands.removeLatest();
975 }
976 for (final Long flagsL : tempFieldFlags) {
977 final long flags = flagsL.longValue();
978 if ((flags & 1 << 19) != 0) {
979 fieldSignature.remove(fieldSignature.size() - 1);
980 }
981 if ((flags & 1 << 17) != 0) {
982 fieldConstantValueKQ.remove(fieldConstantValueKQ.size() - 1);
983 }
984 if ((flags & 1 << 21) != 0) {
985 field_RVA_bands.removeLatest();
986 }
987 if ((flags & 1 << 22) != 0) {
988 field_RIA_bands.removeLatest();
989 }
990 }
991 for (final Long flagsL : tempMethodFlags) {
992 final long flags = flagsL.longValue();
993 if ((flags & 1 << 19) != 0) {
994 methodSignature.remove(methodSignature.size() - 1);
995 }
996 if ((flags & 1 << 18) != 0) {
997 final int exceptions = methodExceptionNumber.remove(methodExceptionNumber.size() - 1);
998 for (int i = 0; i < exceptions; i++) {
999 methodExceptionClasses.remove(methodExceptionClasses.size() - 1);
1000 }
1001 }
1002 if ((flags & 1 << 17) != 0) {
1003 codeMaxLocals.remove(codeMaxLocals.size() - 1);
1004 codeMaxStack.remove(codeMaxStack.size() - 1);
1005 final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
1006 for (int i = 0; i < handlers; i++) {
1007 final int index = codeHandlerStartP.size() - 1;
1008 codeHandlerStartP.remove(index);
1009 codeHandlerEndPO.remove(index);
1010 codeHandlerCatchPO.remove(index);
1011 codeHandlerClass.remove(index);
1012 }
1013 if (!stripDebug) {
1014 final long cdeFlags = codeFlags.remove(codeFlags.size() - 1).longValue();
1015 final int numLocalVariables = codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
1016 for (int i = 0; i < numLocalVariables; i++) {
1017 final int location = codeLocalVariableTableBciP.size() - 1;
1018 codeLocalVariableTableBciP.remove(location);
1019 codeLocalVariableTableSpanO.remove(location);
1020 codeLocalVariableTableNameRU.remove(location);
1021 codeLocalVariableTableTypeRS.remove(location);
1022 codeLocalVariableTableSlot.remove(location);
1023 }
1024 if ((cdeFlags & 1 << 3) != 0) {
1025 final int numLocalVariablesInTypeTable = codeLocalVariableTypeTableN.remove(codeLocalVariableTypeTableN.size() - 1);
1026 for (int i = 0; i < numLocalVariablesInTypeTable; i++) {
1027 final int location = codeLocalVariableTypeTableBciP.size() - 1;
1028 codeLocalVariableTypeTableBciP.remove(location);
1029 codeLocalVariableTypeTableSpanO.remove(location);
1030 codeLocalVariableTypeTableNameRU.remove(location);
1031 codeLocalVariableTypeTableTypeRS.remove(location);
1032 codeLocalVariableTypeTableSlot.remove(location);
1033 }
1034 }
1035 if ((cdeFlags & 1 << 1) != 0) {
1036 final int numLineNumbers = codeLineNumberTableN.remove(codeLineNumberTableN.size() - 1);
1037 for (int i = 0; i < numLineNumbers; i++) {
1038 final int location = codeLineNumberTableBciP.size() - 1;
1039 codeLineNumberTableBciP.remove(location);
1040 codeLineNumberTableLine.remove(location);
1041 }
1042 }
1043 }
1044 }
1045 if ((flags & 1 << 21) != 0) {
1046 method_RVA_bands.removeLatest();
1047 }
1048 if ((flags & 1 << 22) != 0) {
1049 method_RIA_bands.removeLatest();
1050 }
1051 if ((flags & 1 << 23) != 0) {
1052 method_RVPA_bands.removeLatest();
1053 }
1054 if ((flags & 1 << 24) != 0) {
1055 method_RIPA_bands.removeLatest();
1056 }
1057 if ((flags & 1 << 25) != 0) {
1058 method_AD_bands.removeLatest();
1059 }
1060 }
1061 class_this[index] = null;
1062 class_super[index] = null;
1063 class_interface_count[index] = 0;
1064 class_interface[index] = null;
1065 major_versions[index] = 0;
1066 class_flags[index] = 0;
1067 tempFieldDesc.clear();
1068 tempFieldFlags.clear();
1069 tempMethodDesc.clear();
1070 tempMethodFlags.clear();
1071 if (index > 0) {
1072 index--;
1073 }
1074 }
1075
1076 private void renumberBci(final List<Integer> list, final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
1077 for (int i = list.size() - 1; i >= 0; i--) {
1078 final Object label = list.get(i);
1079 if (label instanceof Integer) {
1080 break;
1081 }
1082 if (label instanceof Label) {
1083 list.remove(i);
1084 final Integer bytecodeIndex = labelsToOffsets.get(label);
1085 list.add(i, Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue())));
1086 }
1087 }
1088 }
1089
1090 private void renumberDoubleOffsetBci(final List<Integer> relative, final List<Integer> firstOffset, final List<Object> list, final IntList bciRenumbering,
1091 final Map<Label, Integer> labelsToOffsets) {
1092
1093 for (int i = list.size() - 1; i >= 0; i--) {
1094 final Object label = list.get(i);
1095 if (label instanceof Integer) {
1096 break;
1097 }
1098 if (label instanceof Label) {
1099 list.remove(i);
1100 final Integer bytecodeIndex = labelsToOffsets.get(label);
1101 final Integer renumberedOffset = Integer
1102 .valueOf(bciRenumbering.get(bytecodeIndex.intValue()) - relative.get(i).intValue() - firstOffset.get(i).intValue());
1103 list.add(i, renumberedOffset);
1104 }
1105 }
1106 }
1107
1108 private void renumberOffsetBci(final List<Integer> relative, final List<Integer> list, final IntList bciRenumbering,
1109 final Map<Label, Integer> labelsToOffsets) {
1110 for (int i = list.size() - 1; i >= 0; i--) {
1111 final Object label = list.get(i);
1112 if (label instanceof Integer) {
1113 break;
1114 }
1115 if (label instanceof Label) {
1116 list.remove(i);
1117 final Integer bytecodeIndex = labelsToOffsets.get(label);
1118 final Integer renumberedOffset = Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue()) - relative.get(i).intValue());
1119 list.add(i, renumberedOffset);
1120 }
1121 }
1122 }
1123
1124 private int sum(final int[] ints) {
1125 int sum = 0;
1126 for (final int j : ints) {
1127 sum += j;
1128 }
1129 return sum;
1130 }
1131
1132 private void writeClassAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1133 byte[] encodedBand = encodeFlags("class_flags", class_flags, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_class_flags_hi());
1134 out.write(encodedBand);
1135 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_flags[" + class_flags.length + "]");
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145 encodedBand = encodeBandInt("class_attr_calls", class_attr_calls, Codec.UNSIGNED5);
1146 out.write(encodedBand);
1147 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_attr_calls[" + class_attr_calls.length + "]");
1148
1149 encodedBand = encodeBandInt("classSourceFile", cpEntryOrNullListToArray(classSourceFile), Codec.UNSIGNED5);
1150 out.write(encodedBand);
1151 PackingUtils.log("Wrote " + encodedBand.length + " bytes from classSourceFile[" + classSourceFile.size() + "]");
1152
1153 encodedBand = encodeBandInt("class_enclosing_method_RC", cpEntryListToArray(classEnclosingMethodClass), Codec.UNSIGNED5);
1154 out.write(encodedBand);
1155 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_enclosing_method_RC[" + classEnclosingMethodClass.size() + "]");
1156
1157 encodedBand = encodeBandInt("class_EnclosingMethod_RDN", cpEntryOrNullListToArray(classEnclosingMethodDesc), Codec.UNSIGNED5);
1158 out.write(encodedBand);
1159 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_EnclosingMethod_RDN[" + classEnclosingMethodDesc.size() + "]");
1160
1161 encodedBand = encodeBandInt("class_Signature_RS", cpEntryListToArray(classSignature), Codec.UNSIGNED5);
1162 out.write(encodedBand);
1163 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_Signature_RS[" + classSignature.size() + "]");
1164
1165 class_RVA_bands.pack(out);
1166 class_RIA_bands.pack(out);
1167
1168 encodedBand = encodeBandInt("class_InnerClasses_N", class_InnerClasses_N, Codec.UNSIGNED5);
1169 out.write(encodedBand);
1170 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_N[" + class_InnerClasses_N.length + "]");
1171
1172 encodedBand = encodeBandInt("class_InnerClasses_RC", getInts(class_InnerClasses_RC), Codec.UNSIGNED5);
1173 out.write(encodedBand);
1174 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_RC[" + class_InnerClasses_RC.length + "]");
1175
1176 encodedBand = encodeBandInt("class_InnerClasses_F", class_InnerClasses_F, Codec.UNSIGNED5);
1177 out.write(encodedBand);
1178 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_F[" + class_InnerClasses_F.length + "]");
1179
1180 encodedBand = encodeBandInt("class_InnerClasses_outer_RCN", cpEntryOrNullListToArray(classInnerClassesOuterRCN), Codec.UNSIGNED5);
1181 out.write(encodedBand);
1182 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_outer_RCN[" + classInnerClassesOuterRCN.size() + "]");
1183
1184 encodedBand = encodeBandInt("class_InnerClasses_name_RUN", cpEntryOrNullListToArray(classInnerClassesNameRUN), Codec.UNSIGNED5);
1185 out.write(encodedBand);
1186 PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_name_RUN[" + classInnerClassesNameRUN.size() + "]");
1187
1188 encodedBand = encodeBandInt("classFileVersionMinor", classFileVersionMinor.toArray(), Codec.UNSIGNED5);
1189 out.write(encodedBand);
1190 PackingUtils.log("Wrote " + encodedBand.length + " bytes from classFileVersionMinor[" + classFileVersionMinor.size() + "]");
1191
1192 encodedBand = encodeBandInt("classFileVersionMajor", classFileVersionMajor.toArray(), Codec.UNSIGNED5);
1193 out.write(encodedBand);
1194 PackingUtils.log("Wrote " + encodedBand.length + " bytes from classFileVersionMajor[" + classFileVersionMajor.size() + "]");
1195
1196 for (final NewAttributeBands classAttributeBand : classAttributeBands) {
1197 classAttributeBand.pack(out);
1198 }
1199 }
1200
1201 private void writeCodeAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1202 byte[] encodedBand = encodeFlags("codeFlags", longListToArray(codeFlags), Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_code_flags_hi());
1203 out.write(encodedBand);
1204 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeFlags[" + codeFlags.size() + "]");
1205
1206
1207
1208 encodedBand = encodeBandInt("code_attr_calls", code_attr_calls, Codec.UNSIGNED5);
1209 out.write(encodedBand);
1210 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_attr_calls[" + code_attr_calls.length + "]");
1211
1212 encodedBand = encodeBandInt("code_LineNumberTable_N", codeLineNumberTableN.toArray(), Codec.UNSIGNED5);
1213 out.write(encodedBand);
1214 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_N[" + codeLineNumberTableN.size() + "]");
1215
1216 encodedBand = encodeBandInt("code_LineNumberTable_bci_P", integerListToArray(codeLineNumberTableBciP), Codec.BCI5);
1217 out.write(encodedBand);
1218 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_bci_P[" + codeLineNumberTableBciP.size() + "]");
1219
1220 encodedBand = encodeBandInt("code_LineNumberTable_line", codeLineNumberTableLine.toArray(), Codec.UNSIGNED5);
1221 out.write(encodedBand);
1222 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_line[" + codeLineNumberTableLine.size() + "]");
1223
1224 encodedBand = encodeBandInt("code_LocalVariableTable_N", codeLocalVariableTableN.toArray(), Codec.UNSIGNED5);
1225 out.write(encodedBand);
1226 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_N[" + codeLocalVariableTableN.size() + "]");
1227
1228 encodedBand = encodeBandInt("code_LocalVariableTable_bci_P", integerListToArray(codeLocalVariableTableBciP), Codec.BCI5);
1229 out.write(encodedBand);
1230 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_bci_P[" + codeLocalVariableTableBciP.size() + "]");
1231
1232 encodedBand = encodeBandInt("code_LocalVariableTable_span_O", integerListToArray(codeLocalVariableTableSpanO), Codec.BRANCH5);
1233 out.write(encodedBand);
1234 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_span_O[" + codeLocalVariableTableSpanO.size() + "]");
1235
1236 encodedBand = encodeBandInt("code_LocalVariableTable_name_RU", cpEntryListToArray(codeLocalVariableTableNameRU), Codec.UNSIGNED5);
1237 out.write(encodedBand);
1238 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_name_RU[" + codeLocalVariableTableNameRU.size() + "]");
1239
1240 encodedBand = encodeBandInt("code_LocalVariableTable_type_RS", cpEntryListToArray(codeLocalVariableTableTypeRS), Codec.UNSIGNED5);
1241 out.write(encodedBand);
1242 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_type_RS[" + codeLocalVariableTableTypeRS.size() + "]");
1243
1244 encodedBand = encodeBandInt("code_LocalVariableTable_slot", codeLocalVariableTableSlot.toArray(), Codec.UNSIGNED5);
1245 out.write(encodedBand);
1246 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_slot[" + codeLocalVariableTableSlot.size() + "]");
1247
1248 encodedBand = encodeBandInt("code_LocalVariableTypeTable_N", codeLocalVariableTypeTableN.toArray(), Codec.UNSIGNED5);
1249 out.write(encodedBand);
1250 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_N[" + codeLocalVariableTypeTableN.size() + "]");
1251
1252 encodedBand = encodeBandInt("code_LocalVariableTypeTable_bci_P", integerListToArray(codeLocalVariableTypeTableBciP), Codec.BCI5);
1253 out.write(encodedBand);
1254 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_bci_P[" + codeLocalVariableTypeTableBciP.size() + "]");
1255
1256 encodedBand = encodeBandInt("code_LocalVariableTypeTable_span_O", integerListToArray(codeLocalVariableTypeTableSpanO), Codec.BRANCH5);
1257 out.write(encodedBand);
1258 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_span_O[" + codeLocalVariableTypeTableSpanO.size() + "]");
1259
1260 encodedBand = encodeBandInt("code_LocalVariableTypeTable_name_RU", cpEntryListToArray(codeLocalVariableTypeTableNameRU), Codec.UNSIGNED5);
1261 out.write(encodedBand);
1262 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_name_RU[" + codeLocalVariableTypeTableNameRU.size() + "]");
1263
1264 encodedBand = encodeBandInt("code_LocalVariableTypeTable_type_RS", cpEntryListToArray(codeLocalVariableTypeTableTypeRS), Codec.UNSIGNED5);
1265 out.write(encodedBand);
1266 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_type_RS[" + codeLocalVariableTypeTableTypeRS.size() + "]");
1267
1268 encodedBand = encodeBandInt("code_LocalVariableTypeTable_slot", codeLocalVariableTypeTableSlot.toArray(), Codec.UNSIGNED5);
1269 out.write(encodedBand);
1270 PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_slot[" + codeLocalVariableTypeTableSlot.size() + "]");
1271
1272 for (final NewAttributeBands bands : codeAttributeBands) {
1273 bands.pack(out);
1274 }
1275 }
1276
1277 private void writeCodeBands(final OutputStream out) throws IOException, Pack200Exception {
1278 byte[] encodedBand = encodeBandInt("codeHeaders", codeHeaders, Codec.BYTE1);
1279 out.write(encodedBand);
1280 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHeaders[" + codeHeaders.length + "]");
1281
1282 encodedBand = encodeBandInt("codeMaxStack", codeMaxStack.toArray(), Codec.UNSIGNED5);
1283 out.write(encodedBand);
1284 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxStack[" + codeMaxStack.size() + "]");
1285
1286 encodedBand = encodeBandInt("codeMaxLocals", codeMaxLocals.toArray(), Codec.UNSIGNED5);
1287 out.write(encodedBand);
1288 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxLocals[" + codeMaxLocals.size() + "]");
1289
1290 encodedBand = encodeBandInt("codeHandlerCount", codeHandlerCount.toArray(), Codec.UNSIGNED5);
1291 out.write(encodedBand);
1292 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerCount[" + codeHandlerCount.size() + "]");
1293
1294 encodedBand = encodeBandInt("codeHandlerStartP", integerListToArray(codeHandlerStartP), Codec.BCI5);
1295 out.write(encodedBand);
1296 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerStartP[" + codeHandlerStartP.size() + "]");
1297
1298 encodedBand = encodeBandInt("codeHandlerEndPO", integerListToArray(codeHandlerEndPO), Codec.BRANCH5);
1299 out.write(encodedBand);
1300 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerEndPO[" + codeHandlerEndPO.size() + "]");
1301
1302 encodedBand = encodeBandInt("codeHandlerCatchPO", integerListToArray(codeHandlerCatchPO), Codec.BRANCH5);
1303 out.write(encodedBand);
1304 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerCatchPO[" + codeHandlerCatchPO.size() + "]");
1305
1306 encodedBand = encodeBandInt("codeHandlerClass", cpEntryOrNullListToArray(codeHandlerClass), Codec.UNSIGNED5);
1307 out.write(encodedBand);
1308 PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHandlerClass[" + codeHandlerClass.size() + "]");
1309
1310 writeCodeAttributeBands(out);
1311 }
1312
1313 private void writeFieldAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1314 byte[] encodedBand = encodeFlags("field_flags", field_flags, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_field_flags_hi());
1315 out.write(encodedBand);
1316 PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_flags[" + field_flags.length + "]");
1317
1318
1319
1320 encodedBand = encodeBandInt("field_attr_calls", field_attr_calls, Codec.UNSIGNED5);
1321 out.write(encodedBand);
1322 PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_attr_calls[" + field_attr_calls.length + "]");
1323
1324 encodedBand = encodeBandInt("fieldConstantValueKQ", cpEntryListToArray(fieldConstantValueKQ), Codec.UNSIGNED5);
1325 out.write(encodedBand);
1326 PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldConstantValueKQ[" + fieldConstantValueKQ.size() + "]");
1327
1328 encodedBand = encodeBandInt("fieldSignature", cpEntryListToArray(fieldSignature), Codec.UNSIGNED5);
1329 out.write(encodedBand);
1330 PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldSignature[" + fieldSignature.size() + "]");
1331
1332 field_RVA_bands.pack(out);
1333 field_RIA_bands.pack(out);
1334 for (final NewAttributeBands bands : fieldAttributeBands) {
1335 bands.pack(out);
1336 }
1337 }
1338
1339 private void writeMethodAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
1340 byte[] encodedBand = encodeFlags("method_flags", method_flags, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_method_flags_hi());
1341 out.write(encodedBand);
1342 PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_flags[" + method_flags.length + "]");
1343
1344
1345
1346 encodedBand = encodeBandInt("method_attr_calls", method_attr_calls, Codec.UNSIGNED5);
1347 out.write(encodedBand);
1348 PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_attr_calls[" + method_attr_calls.length + "]");
1349
1350 encodedBand = encodeBandInt("methodExceptionNumber", methodExceptionNumber.toArray(), Codec.UNSIGNED5);
1351 out.write(encodedBand);
1352 PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionNumber[" + methodExceptionNumber.size() + "]");
1353
1354 encodedBand = encodeBandInt("methodExceptionClasses", cpEntryListToArray(methodExceptionClasses), Codec.UNSIGNED5);
1355 out.write(encodedBand);
1356 PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionClasses[" + methodExceptionClasses.size() + "]");
1357
1358 encodedBand = encodeBandInt("methodSignature", cpEntryListToArray(methodSignature), Codec.UNSIGNED5);
1359 out.write(encodedBand);
1360 PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodSignature[" + methodSignature.size() + "]");
1361
1362 method_RVA_bands.pack(out);
1363 method_RIA_bands.pack(out);
1364 method_RVPA_bands.pack(out);
1365 method_RIPA_bands.pack(out);
1366 method_AD_bands.pack(out);
1367 for (final NewAttributeBands bands : methodAttributeBands) {
1368 bands.pack(out);
1369 }
1370 }
1371 }