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