001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.compress.harmony.pack200; 018 019import java.io.IOException; 020import java.io.OutputStream; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Comparator; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.List; 027import java.util.Map; 028import java.util.Set; 029 030import org.apache.commons.compress.harmony.pack200.AttributeDefinitionBands.AttributeDefinition; 031import org.apache.commons.compress.harmony.pack200.IcBands.IcTuple; 032import org.objectweb.asm.Label; 033import org.objectweb.asm.Opcodes; 034 035/** 036 * Class bands (corresponds to the {@code class_bands} set of bands in the pack200 specification) 037 */ 038public class ClassBands extends BandSet { 039 040 private static final class TempParamAnnotation { 041 042 int numParams; 043 int[] annoN; 044 IntList pairN = new IntList(); 045 List<String> typeRS = new ArrayList<>(); 046 List<String> nameRU = new ArrayList<>(); 047 List<String> tags = new ArrayList<>(); 048 List<Object> values = new ArrayList<>(); 049 List<Integer> caseArrayN = new ArrayList<>(); 050 List<String> nestTypeRS = new ArrayList<>(); 051 List<String> nestNameRU = new ArrayList<>(); 052 List<Integer> nestPairN = new ArrayList<>(); 053 054 TempParamAnnotation(final int numParams) { 055 this.numParams = numParams; 056 annoN = new int[numParams]; 057 } 058 059 void addParameterAnnotation(final int parameter, final String desc, final List<String> nameRU, final List<String> tags, 060 final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU, 061 final List<Integer> nestPairN) { 062 annoN[parameter]++; 063 typeRS.add(desc); 064 pairN.add(nameRU.size()); 065 this.nameRU.addAll(nameRU); 066 this.tags.addAll(tags); 067 this.values.addAll(values); 068 this.caseArrayN.addAll(caseArrayN); 069 this.nestTypeRS.addAll(nestTypeRS); 070 this.nestNameRU.addAll(nestNameRU); 071 this.nestPairN.addAll(nestPairN); 072 } 073 } 074 075 private static final long[] EMPTY_LONG_ARRAY = {}; 076 077 protected static int countArgs(final String descriptor) { 078 final int bra = descriptor.indexOf('('); 079 final int ket = descriptor.indexOf(')'); 080 if (bra == -1 || ket == -1 || ket < bra) { 081 throw new IllegalArgumentException("No arguments"); 082 } 083 084 boolean inType = false; 085 boolean consumingNextType = false; 086 int count = 0; 087 for (int i = bra + 1; i < ket; i++) { 088 final char charAt = descriptor.charAt(i); 089 if (inType && charAt == ';') { 090 inType = false; 091 consumingNextType = false; 092 } else if (!inType && charAt == 'L') { 093 inType = true; 094 count++; 095 } else if (charAt == '[') { 096 consumingNextType = true; 097 } else if (inType) { 098 // NOP 099 } 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 // minor_versions = new int[numClasses]; 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// if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated 337// flags &= ~Opcodes.ACC_DEPRECATED; 338// flags |= (1 << 20); 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 // TODO: backwards calls 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) { // ASM uses (1<<17) flag for deprecated 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) { // LocalVariableTypeTable attribute 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 // LocalVariableTable attribute 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) { // not static 477 maxLocals--; // minus 'this' local 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) { // ASM uses (1<<17) flag for deprecated 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() { // All the data for the current class has been 606 // read 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 * All input classes for the segment have now been read in, so this method is called so that this class can calculate/complete anything it could not do 656 * while classes were being read. 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 // Calculate code headers 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) { // Remove the redundant values from 701 // codeHandlerCount, codeMaxLocals and 702 // codeMaxStack 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 // Compute any required IcLocals 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 // should transmit an icLocal entry 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 // Calculate any backwards calls from metadata bands 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 // Sort non-predefined attribute bands 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 * Remove all entries for the current class 956 */ 957 public void removeCurrentClass() { 958 // Note - this doesn't remove any entries added to the constant pool but 959 // that shouldn't be a problem 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) { // has code attribute 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 // TODO: There's probably a nicer way of doing this... 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 // These bands are not needed, but could be used to reduce the size of 1138 // the archive if there are enough different non-standard attributes 1139 // defined that segmentHeader.have_class_flags_hi() is true. The same 1140 // applies to method_attr_count, field_attr_count, code_attr_count etc. 1141 1142 // *class_attr_count :UNSIGNED5 [COUNT(1<<16,...)] 1143 // *class_attr_indexes :UNSIGNED5 [SUM(*class_attr_count)] 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 // *code_attr_count :UNSIGNED5 [COUNT(1<<16,...)] 1207 // *code_attr_indexes :UNSIGNED5 [SUM(*code_attr_count)] 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 // *field_attr_count :UNSIGNED5 [COUNT(1<<16,...)] 1319 // *field_attr_indexes :UNSIGNED5 [SUM(*field_attr_count)] 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 // *method_attr_count :UNSIGNED5 [COUNT(1<<16,...)] 1345 // *method_attr_indexes :UNSIGNED5 [SUM(*method_attr_count)] 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}