You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/09/30 22:12:26 UTC

[commons-compress] 01/02: Use generics

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git

commit 8b8c623ba3212f6805fb5640b9a4be97b1f81bd5
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Fri Sep 30 16:39:09 2022 -0400

    Use generics
    
    Access statics directly
---
 .../commons/compress/harmony/pack200/BandSet.java  |   31 +-
 .../commons/compress/harmony/pack200/BcBands.java  |   66 +-
 .../compress/harmony/pack200/ClassBands.java       | 2862 ++++++++++----------
 .../commons/compress/harmony/pack200/CpBands.java  |    6 +-
 .../compress/harmony/pack200/FileBands.java        |    3 +-
 .../commons/compress/harmony/pack200/IcBands.java  |   14 +-
 .../harmony/pack200/MetadataBandGroup.java         |  281 +-
 .../commons/compress/harmony/pack200/Segment.java  |   88 +-
 .../harmony/unpack200/AttributeLayoutMap.java      |   69 +-
 .../compress/harmony/unpack200/BcBands.java        |   27 +-
 .../compress/harmony/unpack200/ClassBands.java     |   49 +-
 .../compress/harmony/unpack200/CpBands.java        |   56 +-
 .../compress/harmony/unpack200/IcBands.java        |   41 +-
 .../compress/harmony/unpack200/IcTuple.java        |    5 +-
 .../harmony/unpack200/MetadataBandGroup.java       |   18 +-
 .../harmony/unpack200/NewAttributeBands.java       |   50 +-
 .../compress/harmony/unpack200/Segment.java        |   27 +-
 .../harmony/unpack200/SegmentConstantPool.java     |    2 +-
 .../unpack200/SegmentConstantPoolArrayCache.java   |   22 +-
 .../bytecode/AnnotationDefaultAttribute.java       |    2 +-
 .../unpack200/bytecode/AnnotationsAttribute.java   |    9 +-
 .../unpack200/bytecode/BCIRenumberedAttribute.java |    4 +-
 .../harmony/unpack200/bytecode/CPField.java        |    2 +-
 .../harmony/unpack200/bytecode/CPMember.java       |    8 +-
 .../harmony/unpack200/bytecode/CPMethod.java       |    2 +-
 .../unpack200/bytecode/ClassConstantPool.java      |   55 +-
 .../harmony/unpack200/bytecode/CodeAttribute.java  |   28 +-
 .../unpack200/bytecode/ExceptionTableEntry.java    |    8 +-
 .../unpack200/bytecode/InnerClassesAttribute.java  |   12 +-
 .../bytecode/LocalVariableTableAttribute.java      |    6 +-
 .../bytecode/LocalVariableTypeTableAttribute.java  |    6 +-
 .../harmony/unpack200/bytecode/NewAttribute.java   |   22 +-
 ...timeVisibleorInvisibleAnnotationsAttribute.java |    2 +-
 ...leorInvisibleParameterAnnotationsAttribute.java |    6 +-
 .../unpack200/bytecode/forms/LabelForm.java        |    4 +-
 .../unpack200/bytecode/forms/SwitchForm.java       |    4 +-
 .../harmony/pack200/tests/ArchiveTest.java         |    8 +-
 .../harmony/pack200/tests/CodecEncodingTest.java   |    2 +-
 .../harmony/pack200/tests/PackingOptionsTest.java  |   32 +-
 .../harmony/pack200/tests/PopulationCodecTest.java |    5 +-
 .../harmony/pack200/tests/RunCodecTest.java        |   11 +-
 .../harmony/unpack200/tests/ArchiveTest.java       |    8 +-
 .../harmony/unpack200/tests/BcBandsTest.java       |    3 +-
 .../harmony/unpack200/tests/CodeAttributeTest.java |   40 +-
 .../unpack200/tests/NewAttributeBandsTest.java     |    4 +-
 45 files changed, 1977 insertions(+), 2033 deletions(-)

diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/BandSet.java b/src/main/java/org/apache/commons/compress/harmony/pack200/BandSet.java
index 96aa2415..9c98966d 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/BandSet.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/BandSet.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.IntStream;
 
 /**
  * Abstract superclass for a set of bands
@@ -124,10 +125,7 @@ public abstract class BandSet {
                     return band;
                 }
                 if (betterCodec instanceof PopulationCodec) {
-                    final int[] extraSpecifierInfo = results.extraMetadata;
-                    for (int element : extraSpecifierInfo) {
-                        segmentHeader.appendBandCodingSpecifier(element);
-                    }
+                    IntStream.of(results.extraMetadata).forEach(segmentHeader::appendBandCodingSpecifier);
                     return encodedBand;
                 }
                 if (betterCodec instanceof RunCodec) {
@@ -465,22 +463,13 @@ public abstract class BandSet {
         int specifier = 141 + (favouredCodec == null ? 1 : 0) + (4 * tdefL) + (unfavouredCodec == null ? 2 : 0);
         final IntList extraBandMetadata = new IntList(3);
         if (favouredCodec != null) {
-            final int[] specifiers = CodecEncoding.getSpecifier(favouredCodec, null);
-            for (int specifier2 : specifiers) {
-                extraBandMetadata.add(specifier2);
-            }
+            IntStream.of(CodecEncoding.getSpecifier(favouredCodec, null)).forEach(extraBandMetadata::add);
         }
         if (tdefL == 0) {
-            final int[] specifiers = CodecEncoding.getSpecifier(tokenCodec, null);
-            for (int specifier2 : specifiers) {
-                extraBandMetadata.add(specifier2);
-            }
+            IntStream.of(CodecEncoding.getSpecifier(tokenCodec, null)).forEach(extraBandMetadata::add);
         }
         if (unfavouredCodec != null) {
-            final int[] specifiers = CodecEncoding.getSpecifier(unfavouredCodec, null);
-            for (int specifier2 : specifiers) {
-                extraBandMetadata.add(specifier2);
-            }
+            IntStream.of(CodecEncoding.getSpecifier(unfavouredCodec, null)).forEach(extraBandMetadata::add);
         }
         final int[] extraMetadata = extraBandMetadata.toArray();
         final byte[] extraMetadataEncoded = Codec.UNSIGNED5.encode(extraMetadata);
@@ -581,7 +570,7 @@ public abstract class BandSet {
      * @param list conversion source.
      * @return conversion result.
      */
-    protected int[] cpEntryListToArray(final List<ConstantPoolEntry> list) {
+    protected int[] cpEntryListToArray(final List<? extends ConstantPoolEntry> list) {
         final int[] array = new int[list.size()];
         for (int i = 0; i < array.length; i++) {
             array[i] = list.get(i).getIndex();
@@ -595,13 +584,13 @@ public abstract class BandSet {
     /**
      * Converts a list of ConstantPoolEntrys or nulls to an int[] array of their indices +1 (or 0 for nulls)
      *
-     * @param theList conversion source.
+     * @param list conversion source.
      * @return conversion result.
      */
-    protected int[] cpEntryOrNullListToArray(final List<ConstantPoolEntry> theList) {
-        final int[] array = new int[theList.size()];
+    protected int[] cpEntryOrNullListToArray(final List<? extends ConstantPoolEntry> list) {
+        final int[] array = new int[list.size()];
         for (int j = 0; j < array.length; j++) {
-            final ConstantPoolEntry cpEntry = theList.get(j);
+            final ConstantPoolEntry cpEntry = list.get(j);
             array[j] = cpEntry == null ? 0 : cpEntry.getIndex() + 1;
             if (cpEntry != null && cpEntry.getIndex() < 0) {
                 throw new IllegalArgumentException("Index should be > 0");
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/BcBands.java b/src/main/java/org/apache/commons/compress/harmony/pack200/BcBands.java
index c36c5ca2..27594af7 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/BcBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/BcBands.java
@@ -48,20 +48,20 @@ public class BcBands extends BandSet {
     
     // Integers and/or Labels?
     private final List bcLabel = new ArrayList();
-    private final List bcIntref = new ArrayList();
-    private final List bcFloatRef = new ArrayList();
-    private final List bcLongRef = new ArrayList();
-    private final List bcDoubleRef = new ArrayList();
-    private final List bcStringRef = new ArrayList();
-    private final List bcClassRef = new ArrayList();
-    private final List bcFieldRef = new ArrayList();
-    private final List bcMethodRef = new ArrayList();
-    private final List bcIMethodRef = new ArrayList();
-    private List bcThisField = new ArrayList();
-    private final List bcSuperField = new ArrayList();
-    private List bcThisMethod = new ArrayList();
-    private List bcSuperMethod = new ArrayList();
-    private List bcInitRef = new ArrayList();
+    private final List<CPInt> bcIntref = new ArrayList<>();
+    private final List<CPFloat> bcFloatRef = new ArrayList<>();
+    private final List<CPLong> bcLongRef = new ArrayList<>();
+    private final List<CPDouble> bcDoubleRef = new ArrayList<>();
+    private final List<CPString> bcStringRef = new ArrayList<>();
+    private final List<CPClass> bcClassRef = new ArrayList<>();
+    private final List<CPMethodOrField> bcFieldRef = new ArrayList<>();
+    private final List<CPMethodOrField> bcMethodRef = new ArrayList<>();
+    private final List<CPMethodOrField> bcIMethodRef = new ArrayList<>();
+    private List bcThisField = new ArrayList<>();
+    private final List bcSuperField = new ArrayList<>();
+    private List bcThisMethod = new ArrayList<>();
+    private List bcSuperMethod = new ArrayList<>();
+    private List bcInitRef = new ArrayList<>();
 
     private String currentClass;
     private String superClass;
@@ -194,20 +194,18 @@ public class BcBands extends BandSet {
         // out.write(encodeBandInt(integerListToArray(bcEscByte), Codec.BYTE1));
     }
 
-    private List getIndexInClass(final List cPMethodOrFieldList) {
-        final List indices = new ArrayList(cPMethodOrFieldList.size());
+    private List<Integer> getIndexInClass(final List<CPMethodOrField> cPMethodOrFieldList) {
+        final List<Integer> indices = new ArrayList<>(cPMethodOrFieldList.size());
         for (int i = 0; i < cPMethodOrFieldList.size(); i++) {
-            final CPMethodOrField cpMF = (CPMethodOrField) cPMethodOrFieldList.get(i);
-            indices.add(Integer.valueOf(cpMF.getIndexInClass()));
+            indices.add(Integer.valueOf(cPMethodOrFieldList.get(i).getIndexInClass()));
         }
         return indices;
     }
 
-    private List getIndexInClassForConstructor(final List cPMethodList) {
-        final List indices = new ArrayList(cPMethodList.size());
+    private List<Integer> getIndexInClassForConstructor(final List<CPMethodOrField> cPMethodList) {
+        final List<Integer> indices = new ArrayList<>(cPMethodList.size());
         for (int i = 0; i < cPMethodList.size(); i++) {
-            final CPMethodOrField cpMF = (CPMethodOrField) cPMethodList.get(i);
-            indices.add(Integer.valueOf(cpMF.getIndexInClassForConstructor()));
+            indices.add(Integer.valueOf(cPMethodList.get(i).getIndexInClassForConstructor()));
         }
         return indices;
     }
@@ -341,27 +339,27 @@ public class BcBands extends BandSet {
     }
 
     public void visitLdcInsn(final Object cst) {
-        final CPConstant constant = cpBands.getConstant(cst);
+        final CPConstant<?> constant = cpBands.getConstant(cst);
         if (segment.lastConstantHadWideIndex() || constant instanceof CPLong || constant instanceof CPDouble) {
             byteCodeOffset += 3;
             if (constant instanceof CPInt) {
                 bcCodes.add(237); // ildc_w
-                bcIntref.add(constant);
+                bcIntref.add((CPInt) constant);
             } else if (constant instanceof CPFloat) {
                 bcCodes.add(238); // fldc
-                bcFloatRef.add(constant);
+                bcFloatRef.add((CPFloat) constant);
             } else if (constant instanceof CPLong) {
                 bcCodes.add(20); // lldc2_w
-                bcLongRef.add(constant);
+                bcLongRef.add((CPLong) constant);
             } else if (constant instanceof CPDouble) {
                 bcCodes.add(239); // dldc2_w
-                bcDoubleRef.add(constant);
+                bcDoubleRef.add((CPDouble) constant);
             } else if (constant instanceof CPString) {
                 bcCodes.add(19); // aldc
-                bcStringRef.add(constant);
+                bcStringRef.add((CPString) constant);
             } else if (constant instanceof CPClass) {
                 bcCodes.add(236); // cldc
-                bcClassRef.add(constant);
+                bcClassRef.add((CPClass) constant);
             } else {
                 throw new IllegalArgumentException("Constant should not be null");
             }
@@ -369,16 +367,16 @@ public class BcBands extends BandSet {
             byteCodeOffset += 2;
             if (constant instanceof CPInt) {
                 bcCodes.add(234); // ildc
-                bcIntref.add(constant);
+                bcIntref.add((CPInt) constant);
             } else if (constant instanceof CPFloat) {
                 bcCodes.add(235); // fldc
-                bcFloatRef.add(constant);
+                bcFloatRef.add((CPFloat) constant);
             } else if (constant instanceof CPString) {
                 bcCodes.add(18); // aldc
-                bcStringRef.add(constant);
+                bcStringRef.add((CPString) constant);
             } else if (constant instanceof CPClass) {
                 bcCodes.add(233); // cldc
-                bcClassRef.add(constant);
+                bcClassRef.add((CPClass) constant);
             }
         }
         updateRenumbering();
@@ -465,7 +463,7 @@ public class BcBands extends BandSet {
         bcByte.add(dimensions & 0xFF);
     }
 
-    public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label[] labels) {
+    public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) {
         bcCodes.add(TABLESWITCH);
         bcLabel.add(dflt);
         bcLabelRelativeOffsets.add(byteCodeOffset);
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/ClassBands.java b/src/main/java/org/apache/commons/compress/harmony/pack200/ClassBands.java
index 0dccf6da..6730445f 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/ClassBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/ClassBands.java
@@ -32,1450 +32,1426 @@ import org.objectweb.asm.Label;
 import org.objectweb.asm.Opcodes;
 
 /**
- * Class bands (corresponds to the {@code class_bands} set of bands in the pack200 specification)
+ * Class bands (corresponds to the {@code class_bands} set of bands in the
+ * pack200 specification)
  */
 public class ClassBands extends BandSet {
 
-    private final CpBands cpBands;
-    private final AttributeDefinitionBands attrBands;
-
-    private final CPClass[] class_this;
-    private final CPClass[] class_super;
-    private final CPClass[][] class_interface;
-    private final int[] class_interface_count;
-
-    private final int[] major_versions;
-
-    private final long[] class_flags;
-    private int[] class_attr_calls;
-    private final List classSourceFile = new ArrayList();
-    private final List classEnclosingMethodClass = new ArrayList();
-    private final List classEnclosingMethodDesc = new ArrayList();
-    private final List classSignature = new ArrayList();
-
-    private final IntList classFileVersionMinor = new IntList();
-    private final IntList classFileVersionMajor = new IntList();
-
-    private final int[] class_field_count;
-    private final CPNameAndType[][] field_descr;
-    private final long[][] field_flags;
-    private int[] field_attr_calls;
-    private final List fieldConstantValueKQ = new ArrayList();
-    private final List fieldSignature = new ArrayList();
-
-    private final int[] class_method_count;
-    private final CPNameAndType[][] method_descr;
-    private final long[][] method_flags;
-    private int[] method_attr_calls;
-    private final List methodSignature = new ArrayList();
-    private final IntList methodExceptionNumber = new IntList();
-    private final List methodExceptionClasses = new ArrayList();
-
-    private int[] codeHeaders;
-    private final IntList codeMaxStack = new IntList();
-    private final IntList codeMaxLocals = new IntList();
-    private final IntList codeHandlerCount = new IntList();
-    private final List codeHandlerStartP = new ArrayList();
-    private final List codeHandlerEndPO = new ArrayList();
-    private final List codeHandlerCatchPO = new ArrayList();
-    private final List codeHandlerClass = new ArrayList();
-    private final List codeFlags = new ArrayList();
-    private int[] code_attr_calls;
-    private final IntList codeLineNumberTableN = new IntList();
-    private final List codeLineNumberTableBciP = new ArrayList();
-    private final IntList codeLineNumberTableLine = new IntList();
-    private final IntList codeLocalVariableTableN = new IntList();
-    private final List codeLocalVariableTableBciP = new ArrayList();
-    private final List codeLocalVariableTableSpanO = new ArrayList();
-    private final List codeLocalVariableTableNameRU = new ArrayList();
-    private final List codeLocalVariableTableTypeRS = new ArrayList();
-    private final IntList codeLocalVariableTableSlot = new IntList();
-    private final IntList codeLocalVariableTypeTableN = new IntList();
-    private final List codeLocalVariableTypeTableBciP = new ArrayList();
-    private final List codeLocalVariableTypeTableSpanO = new ArrayList();
-    private final List codeLocalVariableTypeTableNameRU = new ArrayList();
-    private final List codeLocalVariableTypeTableTypeRS = new ArrayList();
-    private final IntList codeLocalVariableTypeTableSlot = new IntList();
-
-    private final MetadataBandGroup class_RVA_bands;
-    private final MetadataBandGroup class_RIA_bands;
-    private final MetadataBandGroup field_RVA_bands;
-    private final MetadataBandGroup field_RIA_bands;
-    private final MetadataBandGroup method_RVA_bands;
-    private final MetadataBandGroup method_RIA_bands;
-    private final MetadataBandGroup method_RVPA_bands;
-    private final MetadataBandGroup method_RIPA_bands;
-    private final MetadataBandGroup method_AD_bands;
-
-    private final List classAttributeBands = new ArrayList();
-    private final List methodAttributeBands = new ArrayList();
-    private final List fieldAttributeBands = new ArrayList();
-    private final List codeAttributeBands = new ArrayList();
-
-    private final List tempFieldFlags = new ArrayList();
-    private final List tempFieldDesc = new ArrayList();
-    private final List tempMethodFlags = new ArrayList();
-    private final List tempMethodDesc = new ArrayList();
-    private TempParamAnnotation tempMethodRVPA;
-    private TempParamAnnotation tempMethodRIPA;
-
-    private boolean anySyntheticClasses = false;
-    private boolean anySyntheticFields = false;
-    private boolean anySyntheticMethods = false;
-    private final Segment segment;
-
-    private final Map classReferencesInnerClass = new HashMap();
-    private final boolean stripDebug;
-
-    private int index = 0;
-
-    private int numMethodArgs = 0;
-    private int[] class_InnerClasses_N;
-    private CPClass[] class_InnerClasses_RC;
-    private int[] class_InnerClasses_F;
-    private List classInnerClassesOuterRCN;
-    private List classInnerClassesNameRUN;
-
-    public ClassBands(final Segment segment, final int numClasses, final int effort, final boolean stripDebug)
-        throws IOException {
-        super(effort, segment.getSegmentHeader());
-        this.stripDebug = stripDebug;
-        this.segment = segment;
-        this.cpBands = segment.getCpBands();
-        this.attrBands = segment.getAttrBands();
-        class_this = new CPClass[numClasses];
-        class_super = new CPClass[numClasses];
-        class_interface_count = new int[numClasses];
-        class_interface = new CPClass[numClasses][];
-        class_field_count = new int[numClasses];
-        class_method_count = new int[numClasses];
-        field_descr = new CPNameAndType[numClasses][];
-        field_flags = new long[numClasses][];
-        method_descr = new CPNameAndType[numClasses][];
-        method_flags = new long[numClasses][];
-        for (int i = 0; i < numClasses; i++) {
-            field_flags[i] = new long[0];
-            method_flags[i] = new long[0];
-        }
-        // minor_versions = new int[numClasses];
-        major_versions = new int[numClasses];
-        class_flags = new long[numClasses];
-
-        class_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
-        class_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
-        field_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
-        field_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
-        method_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
-            effort);
-        method_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
-            effort);
-        method_RVPA_bands = new MetadataBandGroup("RVPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
-            effort);
-        method_RIPA_bands = new MetadataBandGroup("RIPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
-            effort);
-        method_AD_bands = new MetadataBandGroup("AD", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
-
-        createNewAttributeBands();
-    }
-
-    private void createNewAttributeBands() throws IOException {
-        final List classAttributeLayouts = attrBands.getClassAttributeLayouts();
-        for (Object classAttributeLayout : classAttributeLayouts) {
-            final AttributeDefinition def = (AttributeDefinition) classAttributeLayout;
-            classAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
-        }
-        final List methodAttributeLayouts = attrBands.getMethodAttributeLayouts();
-        for (Object methodAttributeLayout : methodAttributeLayouts) {
-            final AttributeDefinition def = (AttributeDefinition) methodAttributeLayout;
-            methodAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
-        }
-        final List fieldAttributeLayouts = attrBands.getFieldAttributeLayouts();
-        for (Object fieldAttributeLayout : fieldAttributeLayouts) {
-            final AttributeDefinition def = (AttributeDefinition) fieldAttributeLayout;
-            fieldAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
-        }
-        final List codeAttributeLayouts = attrBands.getCodeAttributeLayouts();
-        for (Object codeAttributeLayout : codeAttributeLayouts) {
-            final AttributeDefinition def = (AttributeDefinition) codeAttributeLayout;
-            codeAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
-        }
-    }
-
-    public void addClass(final int major, int flags, final String className, final String signature,
-        final String superName, final String[] interfaces) {
-        class_this[index] = cpBands.getCPClass(className);
-        class_super[index] = cpBands.getCPClass(superName);
-        class_interface_count[index] = interfaces.length;
-        class_interface[index] = new CPClass[interfaces.length];
-        for (int i = 0; i < interfaces.length; i++) {
-            class_interface[index][i] = cpBands.getCPClass(interfaces[i]);
-        }
-        major_versions[index] = major;
-        class_flags[index] = flags;
-        if (!anySyntheticClasses && ((flags & (1 << 12)) != 0)
-            && segment.getCurrentClassReader().hasSyntheticAttributes()) {
-            cpBands.addCPUtf8("Synthetic");
-            anySyntheticClasses = true;
-        }
-        if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
-            flags = flags & ~Opcodes.ACC_DEPRECATED;
-            flags = flags | (1 << 20);
-        }
-        if (signature != null) {
-            class_flags[index] |= (1 << 19);
-            classSignature.add(cpBands.getCPSignature(signature));
-        }
-    }
-
-    public void currentClassReferencesInnerClass(final CPClass inner) {
-        if (!(index >= class_this.length)) {
-            final CPClass currentClass = class_this[index];
-            if (currentClass != null && !currentClass.equals(inner)
-                && !isInnerClassOf(currentClass.toString(), inner)) {
-                Set referencedInnerClasses = (Set) classReferencesInnerClass.get(currentClass);
-                if (referencedInnerClasses == null) {
-                    referencedInnerClasses = new HashSet();
-                    classReferencesInnerClass.put(currentClass, referencedInnerClasses);
-                }
-                referencedInnerClasses.add(inner);
-            }
-        }
-    }
-
-    private boolean isInnerClassOf(final String possibleInner, final CPClass possibleOuter) {
-        if (isInnerClass(possibleInner)) {
-            final String superClassName = possibleInner.substring(0, possibleInner.lastIndexOf('$'));
-            if (superClassName.equals(possibleOuter.toString())) {
-                return true;
-            }
-            return isInnerClassOf(superClassName, possibleOuter);
-        }
-        return false;
-    }
-
-    private boolean isInnerClass(final String possibleInner) {
-        return possibleInner.indexOf('$') != -1;
-    }
-
-    public void addField(int flags, final String name, final String desc, final String signature, final Object value) {
-        flags = flags & 0xFFFF;
-        tempFieldDesc.add(cpBands.getCPNameAndType(name, desc));
-        if (signature != null) {
-            fieldSignature.add(cpBands.getCPSignature(signature));
-            flags |= (1 << 19);
-        }
-        if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
-            flags = flags & ~Opcodes.ACC_DEPRECATED;
-            flags = flags | (1 << 20);
-        }
-        if (value != null) {
-            fieldConstantValueKQ.add(cpBands.getConstant(value));
-            flags |= (1 << 17);
-        }
-        if (!anySyntheticFields && ((flags & (1 << 12)) != 0)
-            && segment.getCurrentClassReader().hasSyntheticAttributes()) {
-            cpBands.addCPUtf8("Synthetic");
-            anySyntheticFields = true;
-        }
-        tempFieldFlags.add(Long.valueOf(flags));
-    }
-
-    /**
-     * 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 while classes were being read.
-     */
-    public void finaliseBands() {
-        final int defaultMajorVersion = segmentHeader.getDefaultMajorVersion();
-        for (int i = 0; i < class_flags.length; i++) {
-            final int major = major_versions[i];
-            if (major != defaultMajorVersion) {
-                class_flags[i] |= 1 << 24;
-                classFileVersionMajor.add(major);
-                classFileVersionMinor.add(0);
-            }
-        }
-        // Calculate code headers
-        codeHeaders = new int[codeHandlerCount.size()];
-        int removed = 0;
-        for (int i = 0; i < codeHeaders.length; i++) {
-            final int numHandlers = codeHandlerCount.get(i - removed);
-            final int maxLocals = codeMaxLocals.get(i - removed);
-            final int maxStack = codeMaxStack.get(i - removed);
-            if (numHandlers == 0) {
-                final int header = maxLocals * 12 + maxStack + 1;
-                if (header < 145 && maxStack < 12) {
-                    codeHeaders[i] = header;
-                }
-            } else if (numHandlers == 1) {
-                final int header = maxLocals * 8 + maxStack + 145;
-                if (header < 209 && maxStack < 8) {
-                    codeHeaders[i] = header;
-                }
-            } else if (numHandlers == 2) {
-                final int header = maxLocals * 7 + maxStack + 209;
-                if (header < 256 && maxStack < 7) {
-                    codeHeaders[i] = header;
-                }
-            }
-            if (codeHeaders[i] != 0) { // Remove the redundant values from
-                                       // codeHandlerCount, codeMaxLocals and
-                                       // codeMaxStack
-                codeHandlerCount.remove(i - removed);
-                codeMaxLocals.remove(i - removed);
-                codeMaxStack.remove(i - removed);
-                removed++;
-            } else if (!segment.getSegmentHeader().have_all_code_flags()) {
-                codeFlags.add(Long.valueOf(0));
-            }
-        }
-
-        // Compute any required IcLocals
-        final IntList innerClassesN = new IntList();
-        final List icLocal = new ArrayList();
-        for (int i = 0; i < class_this.length; i++) {
-            final CPClass cpClass = class_this[i];
-            final Set referencedInnerClasses = (Set) classReferencesInnerClass.get(cpClass);
-            if (referencedInnerClasses != null) {
-                int innerN = 0;
-                final List innerClasses = segment.getIcBands().getInnerClassesForOuter(cpClass.toString());
-                if (innerClasses != null) {
-                    for (Object element : innerClasses) {
-                        referencedInnerClasses.remove(((IcTuple) element).C);
-                    }
-                }
-                for (Object element : referencedInnerClasses) {
-                    final CPClass inner = (CPClass) element;
-                    final IcTuple icTuple = segment.getIcBands().getIcTuple(inner);
-                    if (icTuple != null && !icTuple.isAnonymous()) {
-                        // should transmit an icLocal entry
-                        icLocal.add(icTuple);
-                        innerN++;
-                    }
-                }
-                if (innerN != 0) {
-                    innerClassesN.add(innerN);
-                    class_flags[i] |= (1 << 23);
-                }
-            }
-        }
-        class_InnerClasses_N = innerClassesN.toArray();
-        class_InnerClasses_RC = new CPClass[icLocal.size()];
-        class_InnerClasses_F = new int[icLocal.size()];
-        classInnerClassesOuterRCN = new ArrayList();
-        classInnerClassesNameRUN = new ArrayList();
-        for (int i = 0; i < class_InnerClasses_RC.length; i++) {
-            final IcTuple icTuple = (IcTuple) icLocal.get(i);
-            class_InnerClasses_RC[i] = (icTuple.C);
-            if (icTuple.C2 == null && icTuple.N == null) {
-                class_InnerClasses_F[i] = 0;
-            } else {
-                if (icTuple.F == 0) {
-                    class_InnerClasses_F[i] = 0x00010000;
-                } else {
-                    class_InnerClasses_F[i] = icTuple.F;
-                }
-                classInnerClassesOuterRCN.add(icTuple.C2);
-                classInnerClassesNameRUN.add(icTuple.N);
-            }
-        }
-        // Calculate any backwards calls from metadata bands
-        final IntList classAttrCalls = new IntList();
-        final IntList fieldAttrCalls = new IntList();
-        final IntList methodAttrCalls = new IntList();
-        final IntList codeAttrCalls = new IntList();
-
-        if (class_RVA_bands.hasContent()) {
-            classAttrCalls.add(class_RVA_bands.numBackwardsCalls());
-        }
-        if (class_RIA_bands.hasContent()) {
-            classAttrCalls.add(class_RIA_bands.numBackwardsCalls());
-        }
-        if (field_RVA_bands.hasContent()) {
-            fieldAttrCalls.add(field_RVA_bands.numBackwardsCalls());
-        }
-        if (field_RIA_bands.hasContent()) {
-            fieldAttrCalls.add(field_RIA_bands.numBackwardsCalls());
-        }
-        if (method_RVA_bands.hasContent()) {
-            methodAttrCalls.add(method_RVA_bands.numBackwardsCalls());
-        }
-        if (method_RIA_bands.hasContent()) {
-            methodAttrCalls.add(method_RIA_bands.numBackwardsCalls());
-        }
-        if (method_RVPA_bands.hasContent()) {
-            methodAttrCalls.add(method_RVPA_bands.numBackwardsCalls());
-        }
-        if (method_RIPA_bands.hasContent()) {
-            methodAttrCalls.add(method_RIPA_bands.numBackwardsCalls());
-        }
-        if (method_AD_bands.hasContent()) {
-            methodAttrCalls.add(method_AD_bands.numBackwardsCalls());
-        }
-
-        // Sort non-predefined attribute bands
-        final Comparator comparator = (arg0, arg1) -> {
-            final NewAttributeBands bands0 = (NewAttributeBands) arg0;
-            final NewAttributeBands bands1 = (NewAttributeBands) arg1;
-            return bands0.getFlagIndex() - bands1.getFlagIndex();
-        };
-        classAttributeBands.sort(comparator);
-        methodAttributeBands.sort(comparator);
-        fieldAttributeBands.sort(comparator);
-        codeAttributeBands.sort(comparator);
-
-        for (Object classAttributeBand : classAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) classAttributeBand;
-            if (bands.isUsedAtLeastOnce()) {
-                final int[] backwardsCallCounts = bands.numBackwardsCalls();
-                for (int backwardsCallCount : backwardsCallCounts) {
-                    classAttrCalls.add(backwardsCallCount);
-                }
-            }
-        }
-        for (Object methodAttributeBand : methodAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) methodAttributeBand;
-            if (bands.isUsedAtLeastOnce()) {
-                final int[] backwardsCallCounts = bands.numBackwardsCalls();
-                for (int backwardsCallCount : backwardsCallCounts) {
-                    methodAttrCalls.add(backwardsCallCount);
-                }
-            }
-        }
-        for (Object fieldAttributeBand : fieldAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) fieldAttributeBand;
-            if (bands.isUsedAtLeastOnce()) {
-                final int[] backwardsCallCounts = bands.numBackwardsCalls();
-                for (int backwardsCallCount : backwardsCallCounts) {
-                    fieldAttrCalls.add(backwardsCallCount);
-                }
-            }
-        }
-        for (Object codeAttributeBand : codeAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) codeAttributeBand;
-            if (bands.isUsedAtLeastOnce()) {
-                final int[] backwardsCallCounts = bands.numBackwardsCalls();
-                for (int backwardsCallCount : backwardsCallCounts) {
-                    codeAttrCalls.add(backwardsCallCount);
-                }
-            }
-        }
-
-        class_attr_calls = classAttrCalls.toArray();
-        field_attr_calls = fieldAttrCalls.toArray();
-        method_attr_calls = methodAttrCalls.toArray();
-        code_attr_calls = codeAttrCalls.toArray();
-    }
-
-    @Override
-    public void pack(final OutputStream out) throws IOException, Pack200Exception {
-        PackingUtils.log("Writing class bands...");
-
-        byte[] encodedBand = encodeBandInt("class_this", getInts(class_this), Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_this[" + class_this.length + "]");
-
-        encodedBand = encodeBandInt("class_super", getInts(class_super), Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_super[" + class_super.length + "]");
-
-        encodedBand = encodeBandInt("class_interface_count", class_interface_count, Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from class_interface_count[" + class_interface_count.length + "]");
-
-        final int totalInterfaces = sum(class_interface_count);
-        final int[] classInterface = new int[totalInterfaces];
-        int k = 0;
-        for (CPClass[] element : class_interface) {
-            if (element != null) {
-                for (final CPClass cpClass : element) {
-                    classInterface[k] = cpClass.getIndex();
-                    k++;
-                }
-            }
-        }
-
-        encodedBand = encodeBandInt("class_interface", classInterface, Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface[" + classInterface.length + "]");
-
-        encodedBand = encodeBandInt("class_field_count", class_field_count, Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from class_field_count[" + class_field_count.length + "]");
-
-        encodedBand = encodeBandInt("class_method_count", class_method_count, Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from class_method_count[" + class_method_count.length + "]");
-
-        final int totalFields = sum(class_field_count);
-        final int[] fieldDescr = new int[totalFields];
-        k = 0;
-        for (int i = 0; i < index; i++) {
-            for (int j = 0; j < field_descr[i].length; j++) {
-                final CPNameAndType descr = field_descr[i][j];
-                fieldDescr[k] = descr.getIndex();
-                k++;
-            }
-        }
-
-        encodedBand = encodeBandInt("field_descr", fieldDescr, Codec.DELTA5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_descr[" + fieldDescr.length + "]");
-
-        writeFieldAttributeBands(out);
-
-        final int totalMethods = sum(class_method_count);
-        final int[] methodDescr = new int[totalMethods];
-        k = 0;
-        for (int i = 0; i < index; i++) {
-            for (int j = 0; j < method_descr[i].length; j++) {
-                final CPNameAndType descr = method_descr[i][j];
-                methodDescr[k] = descr.getIndex();
-                k++;
-            }
-        }
-
-        encodedBand = encodeBandInt("method_descr", methodDescr, Codec.MDELTA5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_descr[" + methodDescr.length + "]");
-
-        writeMethodAttributeBands(out);
-        writeClassAttributeBands(out);
-        writeCodeBands(out);
-    }
-
-    private int sum(final int[] ints) {
-        int sum = 0;
-        for (int j : ints) {
-            sum += j;
-        }
-        return sum;
-    }
-
-    private void writeFieldAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
-        byte[] encodedBand = encodeFlags("field_flags", field_flags, Codec.UNSIGNED5, Codec.UNSIGNED5,
-            segmentHeader.have_field_flags_hi());
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_flags[" + field_flags.length + "]");
-
-        // *field_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
-        // *field_attr_indexes :UNSIGNED5 [SUM(*field_attr_count)]
-        encodedBand = encodeBandInt("field_attr_calls", field_attr_calls, Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from field_attr_calls[" + field_attr_calls.length + "]");
-
-        encodedBand = encodeBandInt("fieldConstantValueKQ", cpEntryListToArray(fieldConstantValueKQ), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from fieldConstantValueKQ[" + fieldConstantValueKQ.size() + "]");
-
-        encodedBand = encodeBandInt("fieldSignature", cpEntryListToArray(fieldSignature), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldSignature[" + fieldSignature.size() + "]");
-
-        field_RVA_bands.pack(out);
-        field_RIA_bands.pack(out);
-        for (Object fieldAttributeBand : fieldAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) fieldAttributeBand;
-            bands.pack(out);
-        }
-    }
-
-    private void writeMethodAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
-        byte[] encodedBand = encodeFlags("method_flags", method_flags, Codec.UNSIGNED5, Codec.UNSIGNED5,
-            segmentHeader.have_method_flags_hi());
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_flags[" + method_flags.length + "]");
-
-        // *method_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
-        // *method_attr_indexes :UNSIGNED5 [SUM(*method_attr_count)]
-        encodedBand = encodeBandInt("method_attr_calls", method_attr_calls, Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from method_attr_calls[" + method_attr_calls.length + "]");
-
-        encodedBand = encodeBandInt("methodExceptionNumber", methodExceptionNumber.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from methodExceptionNumber[" + methodExceptionNumber.size() + "]");
-
-        encodedBand = encodeBandInt("methodExceptionClasses", cpEntryListToArray(methodExceptionClasses),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionClasses["
-            + methodExceptionClasses.size() + "]");
-
-        encodedBand = encodeBandInt("methodSignature", cpEntryListToArray(methodSignature), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodSignature[" + methodSignature.size() + "]");
-
-        method_RVA_bands.pack(out);
-        method_RIA_bands.pack(out);
-        method_RVPA_bands.pack(out);
-        method_RIPA_bands.pack(out);
-        method_AD_bands.pack(out);
-        for (Object methodAttributeBand : methodAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) methodAttributeBand;
-            bands.pack(out);
-        }
-    }
-
-    private void writeClassAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
-        byte[] encodedBand = encodeFlags("class_flags", class_flags, Codec.UNSIGNED5, Codec.UNSIGNED5,
-            segmentHeader.have_class_flags_hi());
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_flags[" + class_flags.length + "]");
-
-        // These bands are not needed, but could be used to reduce the size of
-        // the archive if there are enough different non-standard attributes
-        // defined that segmentHeader.have_class_flags_hi() is true. The same
-        // applies to method_attr_count, field_attr_count, code_attr_count etc.
-
-        // *class_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
-        // *class_attr_indexes :UNSIGNED5 [SUM(*class_attr_count)]
-
-        encodedBand = encodeBandInt("class_attr_calls", class_attr_calls, Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from class_attr_calls[" + class_attr_calls.length + "]");
-
-        encodedBand = encodeBandInt("classSourceFile", cpEntryOrNullListToArray(classSourceFile), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from classSourceFile[" + classSourceFile.size() + "]");
-
-        encodedBand = encodeBandInt("class_enclosing_method_RC", cpEntryListToArray(classEnclosingMethodClass),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_enclosing_method_RC["
-            + classEnclosingMethodClass.size() + "]");
-
-        encodedBand = encodeBandInt("class_EnclosingMethod_RDN", cpEntryOrNullListToArray(classEnclosingMethodDesc),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_EnclosingMethod_RDN["
-            + classEnclosingMethodDesc.size() + "]");
-
-        encodedBand = encodeBandInt("class_Signature_RS", cpEntryListToArray(classSignature), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from class_Signature_RS[" + classSignature.size() + "]");
-
-        class_RVA_bands.pack(out);
-        class_RIA_bands.pack(out);
-
-        encodedBand = encodeBandInt("class_InnerClasses_N", class_InnerClasses_N, Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from class_InnerClasses_N[" + class_InnerClasses_N.length + "]");
-
-        encodedBand = encodeBandInt("class_InnerClasses_RC", getInts(class_InnerClasses_RC), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from class_InnerClasses_RC[" + class_InnerClasses_RC.length + "]");
-
-        encodedBand = encodeBandInt("class_InnerClasses_F", class_InnerClasses_F, Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from class_InnerClasses_F[" + class_InnerClasses_F.length + "]");
-
-        encodedBand = encodeBandInt("class_InnerClasses_outer_RCN", cpEntryOrNullListToArray(classInnerClassesOuterRCN),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_outer_RCN["
-            + classInnerClassesOuterRCN.size() + "]");
-
-        encodedBand = encodeBandInt("class_InnerClasses_name_RUN", cpEntryOrNullListToArray(classInnerClassesNameRUN),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_name_RUN["
-            + classInnerClassesNameRUN.size() + "]");
-
-        encodedBand = encodeBandInt("classFileVersionMinor", classFileVersionMinor.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from classFileVersionMinor[" + classFileVersionMinor.size() + "]");
-
-        encodedBand = encodeBandInt("classFileVersionMajor", classFileVersionMajor.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from classFileVersionMajor[" + classFileVersionMajor.size() + "]");
-
-        for (Object classAttributeBand : classAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) classAttributeBand;
-            bands.pack(out);
-        }
-    }
-
-    private int[] getInts(final CPClass[] cpClasses) {
-        final int[] ints = new int[cpClasses.length];
-        for (int i = 0; i < ints.length; i++) {
-            if (cpClasses[i] != null) {
-                ints[i] = cpClasses[i].getIndex();
-            }
-        }
-        return ints;
-    }
-
-    private void writeCodeBands(final OutputStream out) throws IOException, Pack200Exception {
-        byte[] encodedBand = encodeBandInt("codeHeaders", codeHeaders, Codec.BYTE1);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHeaders[" + codeHeaders.length + "]");
-
-        encodedBand = encodeBandInt("codeMaxStack", codeMaxStack.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxStack[" + codeMaxStack.size() + "]");
-
-        encodedBand = encodeBandInt("codeMaxLocals", codeMaxLocals.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxLocals[" + codeMaxLocals.size() + "]");
-
-        encodedBand = encodeBandInt("codeHandlerCount", codeHandlerCount.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from codeHandlerCount[" + codeHandlerCount.size() + "]");
-
-        encodedBand = encodeBandInt("codeHandlerStartP", integerListToArray(codeHandlerStartP), Codec.BCI5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from codeHandlerStartP[" + codeHandlerStartP.size() + "]");
-
-        encodedBand = encodeBandInt("codeHandlerEndPO", integerListToArray(codeHandlerEndPO), Codec.BRANCH5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from codeHandlerEndPO[" + codeHandlerEndPO.size() + "]");
-
-        encodedBand = encodeBandInt("codeHandlerCatchPO", integerListToArray(codeHandlerCatchPO), Codec.BRANCH5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from codeHandlerCatchPO[" + codeHandlerCatchPO.size() + "]");
-
-        encodedBand = encodeBandInt("codeHandlerClass", cpEntryOrNullListToArray(codeHandlerClass), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils
-            .log("Wrote " + encodedBand.length + " bytes from codeHandlerClass[" + codeHandlerClass.size() + "]");
-
-        writeCodeAttributeBands(out);
-    }
-
-    private void writeCodeAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
-        byte[] encodedBand = encodeFlags("codeFlags", longListToArray(codeFlags), Codec.UNSIGNED5, Codec.UNSIGNED5,
-            segmentHeader.have_code_flags_hi());
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeFlags[" + codeFlags.size() + "]");
-
-        // *code_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
-        // *code_attr_indexes :UNSIGNED5 [SUM(*code_attr_count)]
-        encodedBand = encodeBandInt("code_attr_calls", code_attr_calls, Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_attr_calls[" + code_attr_calls.length + "]");
-
-        encodedBand = encodeBandInt("code_LineNumberTable_N", codeLineNumberTableN.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log(
-            "Wrote " + encodedBand.length + " bytes from code_LineNumberTable_N[" + codeLineNumberTableN.size() + "]");
-
-        encodedBand = encodeBandInt("code_LineNumberTable_bci_P", integerListToArray(codeLineNumberTableBciP),
-            Codec.BCI5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_bci_P["
-            + codeLineNumberTableBciP.size() + "]");
-
-        encodedBand = encodeBandInt("code_LineNumberTable_line", codeLineNumberTableLine.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_line["
-            + codeLineNumberTableLine.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTable_N", codeLocalVariableTableN.toArray(), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_N["
-            + codeLocalVariableTableN.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTable_bci_P", integerListToArray(codeLocalVariableTableBciP),
-            Codec.BCI5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_bci_P["
-            + codeLocalVariableTableBciP.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTable_span_O", integerListToArray(codeLocalVariableTableSpanO),
-            Codec.BRANCH5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_span_O["
-            + codeLocalVariableTableSpanO.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTable_name_RU", cpEntryListToArray(codeLocalVariableTableNameRU),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_name_RU["
-            + codeLocalVariableTableNameRU.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTable_type_RS", cpEntryListToArray(codeLocalVariableTableTypeRS),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_type_RS["
-            + codeLocalVariableTableTypeRS.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTable_slot", codeLocalVariableTableSlot.toArray(),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_slot["
-            + codeLocalVariableTableSlot.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTypeTable_N", codeLocalVariableTypeTableN.toArray(),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_N["
-            + codeLocalVariableTypeTableN.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTypeTable_bci_P",
-            integerListToArray(codeLocalVariableTypeTableBciP), Codec.BCI5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_bci_P["
-            + codeLocalVariableTypeTableBciP.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTypeTable_span_O",
-            integerListToArray(codeLocalVariableTypeTableSpanO), Codec.BRANCH5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_span_O["
-            + codeLocalVariableTypeTableSpanO.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTypeTable_name_RU",
-            cpEntryListToArray(codeLocalVariableTypeTableNameRU), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_name_RU["
-            + codeLocalVariableTypeTableNameRU.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTypeTable_type_RS",
-            cpEntryListToArray(codeLocalVariableTypeTableTypeRS), Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_type_RS["
-            + codeLocalVariableTypeTableTypeRS.size() + "]");
-
-        encodedBand = encodeBandInt("code_LocalVariableTypeTable_slot", codeLocalVariableTypeTableSlot.toArray(),
-            Codec.UNSIGNED5);
-        out.write(encodedBand);
-        PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_slot["
-            + codeLocalVariableTypeTableSlot.size() + "]");
-
-        for (Object codeAttributeBand : codeAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) codeAttributeBand;
-            bands.pack(out);
-        }
-    }
-
-    public void addMethod(int flags, final String name, final String desc, final String signature,
-        final String[] exceptions) {
-        final CPNameAndType nt = cpBands.getCPNameAndType(name, desc);
-        tempMethodDesc.add(nt);
-        if (signature != null) {
-            methodSignature.add(cpBands.getCPSignature(signature));
-            flags |= (1 << 19);
-        }
-        if (exceptions != null) {
-            methodExceptionNumber.add(exceptions.length);
-            for (String exception : exceptions) {
-                methodExceptionClasses.add(cpBands.getCPClass(exception));
-            }
-            flags |= (1 << 18);
-        }
-        if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
-            flags = flags & ~Opcodes.ACC_DEPRECATED;
-            flags = flags | (1 << 20);
-        }
-        tempMethodFlags.add(Long.valueOf(flags));
-        numMethodArgs = countArgs(desc);
-        if (!anySyntheticMethods && ((flags & (1 << 12)) != 0)
-            && segment.getCurrentClassReader().hasSyntheticAttributes()) {
-            cpBands.addCPUtf8("Synthetic");
-            anySyntheticMethods = true;
-        }
-    }
-
-    public void endOfMethod() {
-        if (tempMethodRVPA != null) {
-            method_RVPA_bands.addParameterAnnotation(tempMethodRVPA.numParams, tempMethodRVPA.annoN,
-                tempMethodRVPA.pairN, tempMethodRVPA.typeRS, tempMethodRVPA.nameRU, tempMethodRVPA.t,
-                tempMethodRVPA.values, tempMethodRVPA.caseArrayN, tempMethodRVPA.nestTypeRS, tempMethodRVPA.nestNameRU,
-                tempMethodRVPA.nestPairN);
-            tempMethodRVPA = null;
-        }
-        if (tempMethodRIPA != null) {
-            method_RIPA_bands.addParameterAnnotation(tempMethodRIPA.numParams, tempMethodRIPA.annoN,
-                tempMethodRIPA.pairN, tempMethodRIPA.typeRS, tempMethodRIPA.nameRU, tempMethodRIPA.t,
-                tempMethodRIPA.values, tempMethodRIPA.caseArrayN, tempMethodRIPA.nestTypeRS, tempMethodRIPA.nestNameRU,
-                tempMethodRIPA.nestPairN);
-            tempMethodRIPA = null;
-        }
-        if (codeFlags.size() > 0) {
-            final long latestCodeFlag = ((Long) codeFlags.get(codeFlags.size() - 1)).longValue();
-            final int latestLocalVariableTableN = codeLocalVariableTableN.get(codeLocalVariableTableN.size() - 1);
-            if (latestCodeFlag == (1 << 2) && latestLocalVariableTableN == 0) {
-                codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
-                codeFlags.remove(codeFlags.size() - 1);
-                codeFlags.add(Integer.valueOf(0));
-            }
-        }
-    }
-
-    protected static int countArgs(final String descriptor) {
-        final int bra = descriptor.indexOf('(');
-        final int ket = descriptor.indexOf(')');
-        if (bra == -1 || ket == -1 || ket < bra) {
-            throw new IllegalArgumentException("No arguments");
-        }
-
-        boolean inType = false;
-        boolean consumingNextType = false;
-        int count = 0;
-        for (int i = bra + 1; i < ket; i++) {
-            final char charAt = descriptor.charAt(i);
-            if (inType && charAt == ';') {
-                inType = false;
-                consumingNextType = false;
-            } else if (!inType && charAt == 'L') {
-                inType = true;
-                count++;
-            } else if (charAt == '[') {
-                consumingNextType = true;
-            } else if (inType) {
-                // NOP
-            } else if (consumingNextType) {
-                count++;
-                consumingNextType = false;
-            } else if (charAt == 'D' || charAt == 'J') {
-                count += 2;
-            } else {
-                count++;
-            }
-        }
-        return count;
-    }
-
-    public void endOfClass() { // All the data for the current class has been
-                               // read
-        final int numFields = tempFieldDesc.size();
-        class_field_count[index] = numFields;
-        field_descr[index] = new CPNameAndType[numFields];
-        field_flags[index] = new long[numFields];
-        for (int i = 0; i < numFields; i++) {
-            field_descr[index][i] = (CPNameAndType) tempFieldDesc.get(i);
-            field_flags[index][i] = ((Long) tempFieldFlags.get(i)).longValue();
-        }
-        final int numMethods = tempMethodDesc.size();
-        class_method_count[index] = numMethods;
-        method_descr[index] = new CPNameAndType[numMethods];
-        method_flags[index] = new long[numMethods];
-        for (int i = 0; i < numMethods; i++) {
-            method_descr[index][i] = (CPNameAndType) tempMethodDesc.get(i);
-            method_flags[index][i] = ((Long) tempMethodFlags.get(i)).longValue();
-        }
-        tempFieldDesc.clear();
-        tempFieldFlags.clear();
-        tempMethodDesc.clear();
-        tempMethodFlags.clear();
-        index++;
-    }
-
-    public void addSourceFile(final String source) {
-        String implicitSourceFileName = class_this[index].toString();
-        if (implicitSourceFileName.indexOf('$') != -1) {
-            implicitSourceFileName = implicitSourceFileName.substring(0, implicitSourceFileName.indexOf('$'));
-        }
-        implicitSourceFileName = implicitSourceFileName.substring(implicitSourceFileName.lastIndexOf('/') + 1)
-            + ".java";
-        if (source.equals(implicitSourceFileName)) {
-            classSourceFile.add(null);
-        } else {
-            classSourceFile.add(cpBands.getCPUtf8(source));
-        }
-        class_flags[index] |= (1 << 17);
-    }
-
-    public void addEnclosingMethod(final String owner, final String name, final String desc) {
-        class_flags[index] |= (1 << 18);
-        classEnclosingMethodClass.add(cpBands.getCPClass(owner));
-        classEnclosingMethodDesc.add(name == null ? null : cpBands.getCPNameAndType(name, desc));
-    }
-
-    public void addClassAttribute(final NewAttribute attribute) {
-        // TODO: backwards calls
-        final String attributeName = attribute.type;
-        for (Object classAttributeBand : classAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) classAttributeBand;
-            if (bands.getAttributeName().equals(attributeName)) {
-                bands.addAttribute(attribute);
-                final int flagIndex = bands.getFlagIndex();
-                class_flags[index] |= (1 << flagIndex);
-                return;
-            }
-        }
-        throw new IllegalArgumentException("No suitable definition for " + attributeName);
-    }
-
-    public void addFieldAttribute(final NewAttribute attribute) {
-        final String attributeName = attribute.type;
-        for (Object fieldAttributeBand : fieldAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) fieldAttributeBand;
-            if (bands.getAttributeName().equals(attributeName)) {
-                bands.addAttribute(attribute);
-                final int flagIndex = bands.getFlagIndex();
-                final Long flags = (Long) tempFieldFlags.remove(tempFieldFlags.size() - 1);
-                tempFieldFlags.add(Long.valueOf(flags.longValue() | (1 << flagIndex)));
-                return;
-            }
-        }
-        throw new IllegalArgumentException("No suitable definition for " + attributeName);
-    }
-
-    public void addMethodAttribute(final NewAttribute attribute) {
-        final String attributeName = attribute.type;
-        for (Object methodAttributeBand : methodAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) methodAttributeBand;
-            if (bands.getAttributeName().equals(attributeName)) {
-                bands.addAttribute(attribute);
-                final int flagIndex = bands.getFlagIndex();
-                final Long flags = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-                tempMethodFlags.add(Long.valueOf(flags.longValue() | (1 << flagIndex)));
-                return;
-            }
-        }
-        throw new IllegalArgumentException("No suitable definition for " + attributeName);
-    }
-
-    public void addCodeAttribute(final NewAttribute attribute) {
-        final String attributeName = attribute.type;
-        for (Object codeAttributeBand : codeAttributeBands) {
-            final NewAttributeBands bands = (NewAttributeBands) codeAttributeBand;
-            if (bands.getAttributeName().equals(attributeName)) {
-                bands.addAttribute(attribute);
-                final int flagIndex = bands.getFlagIndex();
-                final Long flags = (Long) codeFlags.remove(codeFlags.size() - 1);
-                codeFlags.add(Long.valueOf(flags.longValue() | (1 << flagIndex)));
-                return;
-            }
-        }
-        throw new IllegalArgumentException("No suitable definition for " + attributeName);
-    }
-
-    public void addMaxStack(final int maxStack, int maxLocals) {
-        final Long latestFlag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-        final Long newFlag = Long.valueOf(latestFlag.intValue() | (1 << 17));
-        tempMethodFlags.add(newFlag);
-        codeMaxStack.add(maxStack);
-        if ((newFlag.longValue() & (1 << 3)) == 0) { // not static
-            maxLocals--; // minus 'this' local
-        }
-        maxLocals -= numMethodArgs;
-        codeMaxLocals.add(maxLocals);
-    }
-
-    public void addCode() {
-        codeHandlerCount.add(0);
-        if (!stripDebug) {
-            codeFlags.add(Long.valueOf(1 << 2));
-            codeLocalVariableTableN.add(0);
-        }
-    }
-
-    public void addHandler(final Label start, final Label end, final Label handler, final String type) {
-        final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
-        codeHandlerCount.add(handlers + 1);
-        codeHandlerStartP.add(start);
-        codeHandlerEndPO.add(end);
-        codeHandlerCatchPO.add(handler);
-        codeHandlerClass.add(type == null ? null : cpBands.getCPClass(type));
-    }
-
-    public void addLineNumber(final int line, final Label start) {
-        final Long latestCodeFlag = (Long) codeFlags.get(codeFlags.size() - 1);
-        if ((latestCodeFlag.intValue() & (1 << 1)) == 0) {
-            codeFlags.remove(codeFlags.size() - 1);
-            codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | (1 << 1)));
-            codeLineNumberTableN.add(1);
-        } else {
-            codeLineNumberTableN.increment(codeLineNumberTableN.size() - 1);
-        }
-        codeLineNumberTableLine.add(line);
-        codeLineNumberTableBciP.add(start);
-    }
-
-    public void addLocalVariable(final String name, final String desc, final String signature, final Label start,
-        final Label end, final int indx) {
-        if (signature != null) { // LocalVariableTypeTable attribute
-            final Long latestCodeFlag = (Long) codeFlags.get(codeFlags.size() - 1);
-            if ((latestCodeFlag.intValue() & (1 << 3)) == 0) {
-                codeFlags.remove(codeFlags.size() - 1);
-                codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | (1 << 3)));
-                codeLocalVariableTypeTableN.add(1);
-            } else {
-                codeLocalVariableTypeTableN.increment(codeLocalVariableTypeTableN.size() - 1);
-            }
-            codeLocalVariableTypeTableBciP.add(start);
-            codeLocalVariableTypeTableSpanO.add(end);
-            codeLocalVariableTypeTableNameRU.add(cpBands.getCPUtf8(name));
-            codeLocalVariableTypeTableTypeRS.add(cpBands.getCPSignature(signature));
-            codeLocalVariableTypeTableSlot.add(indx);
-        }
-        // LocalVariableTable attribute
-        codeLocalVariableTableN.increment(codeLocalVariableTableN.size() - 1);
-        codeLocalVariableTableBciP.add(start);
-        codeLocalVariableTableSpanO.add(end);
-        codeLocalVariableTableNameRU.add(cpBands.getCPUtf8(name));
-        codeLocalVariableTableTypeRS.add(cpBands.getCPSignature(desc));
-        codeLocalVariableTableSlot.add(indx);
-    }
-
-    public void doBciRenumbering(final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
-        renumberBci(codeLineNumberTableBciP, bciRenumbering, labelsToOffsets);
-        renumberBci(codeLocalVariableTableBciP, bciRenumbering, labelsToOffsets);
-        renumberOffsetBci(codeLocalVariableTableBciP, codeLocalVariableTableSpanO, bciRenumbering, labelsToOffsets);
-        renumberBci(codeLocalVariableTypeTableBciP, bciRenumbering, labelsToOffsets);
-        renumberOffsetBci(codeLocalVariableTypeTableBciP, codeLocalVariableTypeTableSpanO, bciRenumbering,
-            labelsToOffsets);
-        renumberBci(codeHandlerStartP, bciRenumbering, labelsToOffsets);
-        renumberOffsetBci(codeHandlerStartP, codeHandlerEndPO, bciRenumbering, labelsToOffsets);
-        renumberDoubleOffsetBci(codeHandlerStartP, codeHandlerEndPO, codeHandlerCatchPO, bciRenumbering,
-            labelsToOffsets);
-
-        for (Object classAttributeBand : classAttributeBands) {
-            final NewAttributeBands newAttributeBandSet = (NewAttributeBands) classAttributeBand;
-            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
-        }
-        for (Object methodAttributeBand : methodAttributeBands) {
-            final NewAttributeBands newAttributeBandSet = (NewAttributeBands) methodAttributeBand;
-            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
-        }
-        for (Object fieldAttributeBand : fieldAttributeBands) {
-            final NewAttributeBands newAttributeBandSet = (NewAttributeBands) fieldAttributeBand;
-            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
-        }
-        for (Object codeAttributeBand : codeAttributeBands) {
-            final NewAttributeBands newAttributeBandSet = (NewAttributeBands) codeAttributeBand;
-            newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
-        }
-    }
-
-    private void renumberBci(final List list, final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
-        for (int i = list.size() - 1; i >= 0; i--) {
-            final Object label = list.get(i);
-            if (label instanceof Integer) {
-                break;
-            }
-            if (label instanceof Label) {
-                list.remove(i);
-                final Integer bytecodeIndex = labelsToOffsets.get(label);
-                list.add(i, Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue())));
-            }
-        }
-    }
-
-    private void renumberOffsetBci(final List relative, final List list, final IntList bciRenumbering,
-        final Map<Label, Integer> labelsToOffsets) {
-        for (int i = list.size() - 1; i >= 0; i--) {
-            final Object label = list.get(i);
-            if (label instanceof Integer) {
-                break;
-            }
-            if (label instanceof Label) {
-                list.remove(i);
-                final Integer bytecodeIndex = labelsToOffsets.get(label);
-                final Integer renumberedOffset = Integer
-                    .valueOf(bciRenumbering.get(bytecodeIndex.intValue()) - ((Integer) relative.get(i)).intValue());
-                list.add(i, renumberedOffset);
-            }
-        }
-    }
-
-    private void renumberDoubleOffsetBci(final List relative, final List firstOffset, final List list,
-        final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
-        // TODO: There's probably a nicer way of doing this...
-        for (int i = list.size() - 1; i >= 0; i--) {
-            final Object label = list.get(i);
-            if (label instanceof Integer) {
-                break;
-            }
-            if (label instanceof Label) {
-                list.remove(i);
-                final Integer bytecodeIndex = labelsToOffsets.get(label);
-                final Integer renumberedOffset = Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue())
-                    - ((Integer) relative.get(i)).intValue() - ((Integer) firstOffset.get(i)).intValue());
-                list.add(i, renumberedOffset);
-            }
-        }
-    }
-
-    public boolean isAnySyntheticClasses() {
-        return anySyntheticClasses;
-    }
-
-    public boolean isAnySyntheticFields() {
-        return anySyntheticFields;
-    }
-
-    public boolean isAnySyntheticMethods() {
-        return anySyntheticMethods;
-    }
-
-    public void addParameterAnnotation(final int parameter, final String desc, final boolean visible, final List nameRU,
-        final List t, final List values, final List caseArrayN, final List nestTypeRS, final List nestNameRU,
-        final List nestPairN) {
-        if (visible) {
-            if (tempMethodRVPA == null) {
-                tempMethodRVPA = new TempParamAnnotation(numMethodArgs);
-                tempMethodRVPA.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS,
-                    nestNameRU, nestPairN);
-            }
-            final Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-            tempMethodFlags.add(Long.valueOf(flag.longValue() | (1 << 23)));
-        } else {
-            if (tempMethodRIPA == null) {
-                tempMethodRIPA = new TempParamAnnotation(numMethodArgs);
-                tempMethodRIPA.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS,
-                    nestNameRU, nestPairN);
-            }
-            final Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-            tempMethodFlags.add(Long.valueOf(flag.longValue() | (1 << 24)));
-        }
-    }
-
-    private static class TempParamAnnotation {
-
-        int numParams;
-        int[] annoN;
-        IntList pairN = new IntList();
-        List typeRS = new ArrayList();
-        List nameRU = new ArrayList();
-        List t = new ArrayList();
-        List values = new ArrayList();
-        List caseArrayN = new ArrayList();
-        List nestTypeRS = new ArrayList();
-        List nestNameRU = new ArrayList();
-        List nestPairN = new ArrayList();
-
-        public TempParamAnnotation(final int numParams) {
-            this.numParams = numParams;
-            annoN = new int[numParams];
-        }
-
-        public void addParameterAnnotation(final int parameter, final String desc, final List nameRU, final List t,
-            final List values, final List caseArrayN, final List nestTypeRS, final List nestNameRU,
-            final List nestPairN) {
-            annoN[parameter]++;
-            typeRS.add(desc);
-            pairN.add(nameRU.size());
-            this.nameRU.addAll(nameRU);
-            this.t.addAll(t);
-            this.values.addAll(values);
-            this.caseArrayN.addAll(caseArrayN);
-            this.nestTypeRS.addAll(nestTypeRS);
-            this.nestNameRU.addAll(nestNameRU);
-            this.nestPairN.addAll(nestPairN);
-        }
-    }
-
-    public void addAnnotation(final int context, final String desc, final boolean visible, final List nameRU,
-        final List t, final List values, final List caseArrayN, final List nestTypeRS, final List nestNameRU,
-        final List nestPairN) {
-        switch (context) {
-        case MetadataBandGroup.CONTEXT_CLASS:
-            if (visible) {
-                class_RVA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-                if ((class_flags[index] & (1 << 21)) != 0) {
-                    class_RVA_bands.incrementAnnoN();
-                } else {
-                    class_RVA_bands.newEntryInAnnoN();
-                    class_flags[index] = class_flags[index] | (1 << 21);
-                }
-            } else {
-                class_RIA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-                if ((class_flags[index] & (1 << 22)) != 0) {
-                    class_RIA_bands.incrementAnnoN();
-                } else {
-                    class_RIA_bands.newEntryInAnnoN();
-                    class_flags[index] = class_flags[index] | (1 << 22);
-                }
-            }
-            break;
-        case MetadataBandGroup.CONTEXT_FIELD:
-            if (visible) {
-                field_RVA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-                final Long flag = (Long) tempFieldFlags.remove(tempFieldFlags.size() - 1);
-                if ((flag.intValue() & (1 << 21)) != 0) {
-                    field_RVA_bands.incrementAnnoN();
-                } else {
-                    field_RVA_bands.newEntryInAnnoN();
-                }
-                tempFieldFlags.add(Long.valueOf(flag.intValue() | (1 << 21)));
-            } else {
-                field_RIA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-                final Long flag = (Long) tempFieldFlags.remove(tempFieldFlags.size() - 1);
-                if ((flag.intValue() & (1 << 22)) != 0) {
-                    field_RIA_bands.incrementAnnoN();
-                } else {
-                    field_RIA_bands.newEntryInAnnoN();
-                }
-                tempFieldFlags.add(Long.valueOf(flag.intValue() | (1 << 22)));
-            }
-            break;
-        case MetadataBandGroup.CONTEXT_METHOD:
-            if (visible) {
-                method_RVA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-                final Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-                if ((flag.intValue() & (1 << 21)) != 0) {
-                    method_RVA_bands.incrementAnnoN();
-                } else {
-                    method_RVA_bands.newEntryInAnnoN();
-                }
-                tempMethodFlags.add(Long.valueOf(flag.intValue() | (1 << 21)));
-            } else {
-                method_RIA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-                final Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-                if ((flag.intValue() & (1 << 22)) != 0) {
-                    method_RIA_bands.incrementAnnoN();
-                } else {
-                    method_RIA_bands.newEntryInAnnoN();
-                }
-                tempMethodFlags.add(Long.valueOf(flag.intValue() | (1 << 22)));
-            }
-            break;
-        }
-    }
-
-    public void addAnnotationDefault(final List nameRU, final List t, final List values, final List caseArrayN,
-        final List nestTypeRS, final List nestNameRU, final List nestPairN) {
-        method_AD_bands.addAnnotation(null, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
-        final Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
-        tempMethodFlags.add(Long.valueOf(flag.longValue() | (1 << 25)));
-    }
-
-    /**
-     * Remove all entries for the current class
-     */
-    public void removeCurrentClass() {
-        // Note - this doesn't remove any entries added to the constant pool but
-        // that shouldn't be a problem
-        if ((class_flags[index] & (1 << 17)) != 0) {
-            classSourceFile.remove(classSourceFile.size() - 1);
-        }
-        if ((class_flags[index] & (1 << 18)) != 0) {
-            classEnclosingMethodClass.remove(classEnclosingMethodClass.size() - 1);
-            classEnclosingMethodDesc.remove(classEnclosingMethodDesc.size() - 1);
-        }
-        if ((class_flags[index] & (1 << 19)) != 0) {
-            classSignature.remove(classSignature.size() - 1);
-        }
-        if ((class_flags[index] & (1 << 21)) != 0) {
-            class_RVA_bands.removeLatest();
-        }
-        if ((class_flags[index] & (1 << 22)) != 0) {
-            class_RIA_bands.removeLatest();
-        }
-        for (Object tempFieldFlag : tempFieldFlags) {
-            final Long flagsL = (Long) tempFieldFlag;
-            final long flags = flagsL.longValue();
-            if ((flags & (1 << 19)) != 0) {
-                fieldSignature.remove(fieldSignature.size() - 1);
-            }
-            if ((flags & (1 << 17)) != 0) {
-                fieldConstantValueKQ.remove(fieldConstantValueKQ.size() - 1);
-            }
-            if ((flags & (1 << 21)) != 0) {
-                field_RVA_bands.removeLatest();
-            }
-            if ((flags & (1 << 22)) != 0) {
-                field_RIA_bands.removeLatest();
-            }
-        }
-        for (Object tempMethodFlag : tempMethodFlags) {
-            final Long flagsL = (Long) tempMethodFlag;
-            final long flags = flagsL.longValue();
-            if ((flags & (1 << 19)) != 0) {
-                methodSignature.remove(methodSignature.size() - 1);
-            }
-            if ((flags & (1 << 18)) != 0) {
-                final int exceptions = methodExceptionNumber.remove(methodExceptionNumber.size() - 1);
-                for (int i = 0; i < exceptions; i++) {
-                    methodExceptionClasses.remove(methodExceptionClasses.size() - 1);
-                }
-            }
-            if ((flags & (1 << 17)) != 0) { // has code attribute
-                codeMaxLocals.remove(codeMaxLocals.size() - 1);
-                codeMaxStack.remove(codeMaxStack.size() - 1);
-                final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
-                for (int i = 0; i < handlers; i++) {
-                    final int index = codeHandlerStartP.size() - 1;
-                    codeHandlerStartP.remove(index);
-                    codeHandlerEndPO.remove(index);
-                    codeHandlerCatchPO.remove(index);
-                    codeHandlerClass.remove(index);
-                }
-                if (!stripDebug) {
-                    final long cdeFlags = ((Long) codeFlags.remove(codeFlags.size() - 1)).longValue();
-                    final int numLocalVariables = codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
-                    for (int i = 0; i < numLocalVariables; i++) {
-                        final int location = codeLocalVariableTableBciP.size() - 1;
-                        codeLocalVariableTableBciP.remove(location);
-                        codeLocalVariableTableSpanO.remove(location);
-                        codeLocalVariableTableNameRU.remove(location);
-                        codeLocalVariableTableTypeRS.remove(location);
-                        codeLocalVariableTableSlot.remove(location);
-                    }
-                    if ((cdeFlags & (1 << 3)) != 0) {
-                        final int numLocalVariablesInTypeTable = codeLocalVariableTypeTableN
-                            .remove(codeLocalVariableTypeTableN.size() - 1);
-                        for (int i = 0; i < numLocalVariablesInTypeTable; i++) {
-                            final int location = codeLocalVariableTypeTableBciP.size() - 1;
-                            codeLocalVariableTypeTableBciP.remove(location);
-                            codeLocalVariableTypeTableSpanO.remove(location);
-                            codeLocalVariableTypeTableNameRU.remove(location);
-                            codeLocalVariableTypeTableTypeRS.remove(location);
-                            codeLocalVariableTypeTableSlot.remove(location);
-                        }
-                    }
-                    if ((cdeFlags & (1 << 1)) != 0) {
-                        final int numLineNumbers = codeLineNumberTableN.remove(codeLineNumberTableN.size() - 1);
-                        for (int i = 0; i < numLineNumbers; i++) {
-                            final int location = codeLineNumberTableBciP.size() - 1;
-                            codeLineNumberTableBciP.remove(location);
-                            codeLineNumberTableLine.remove(location);
-                        }
-                    }
-                }
-            }
-            if ((flags & (1 << 21)) != 0) {
-                method_RVA_bands.removeLatest();
-            }
-            if ((flags & (1 << 22)) != 0) {
-                method_RIA_bands.removeLatest();
-            }
-            if ((flags & (1 << 23)) != 0) {
-                method_RVPA_bands.removeLatest();
-            }
-            if ((flags & (1 << 24)) != 0) {
-                method_RIPA_bands.removeLatest();
-            }
-            if ((flags & (1 << 25)) != 0) {
-                method_AD_bands.removeLatest();
-            }
-        }
-        class_this[index] = null;
-        class_super[index] = null;
-        class_interface_count[index] = 0;
-        class_interface[index] = null;
-        major_versions[index] = 0;
-        class_flags[index] = 0;
-        tempFieldDesc.clear();
-        tempFieldFlags.clear();
-        tempMethodDesc.clear();
-        tempMethodFlags.clear();
-        if (index > 0) {
-            index--;
-        }
-    }
-
-    public int numClassesProcessed() {
-        return index;
-    }
+	private final CpBands cpBands;
+	private final AttributeDefinitionBands attrBands;
+
+	private final CPClass[] class_this;
+	private final CPClass[] class_super;
+	private final CPClass[][] class_interface;
+	private final int[] class_interface_count;
+
+	private final int[] major_versions;
+
+	private final long[] class_flags;
+	private int[] class_attr_calls;
+	private final List<CPUTF8> classSourceFile = new ArrayList<>();
+	private final List<ConstantPoolEntry> classEnclosingMethodClass = new ArrayList<>();
+	private final List<ConstantPoolEntry> classEnclosingMethodDesc = new ArrayList<>();
+	private final List<CPSignature> classSignature = new ArrayList<>();
+
+	private final IntList classFileVersionMinor = new IntList();
+	private final IntList classFileVersionMajor = new IntList();
+
+	private final int[] class_field_count;
+	private final CPNameAndType[][] field_descr;
+	private final long[][] field_flags;
+	private int[] field_attr_calls;
+	private final List<CPConstant<?>> fieldConstantValueKQ = new ArrayList<>();
+	private final List<CPSignature> fieldSignature = new ArrayList<>();
+
+	private final int[] class_method_count;
+	private final CPNameAndType[][] method_descr;
+	private final long[][] method_flags;
+	private int[] method_attr_calls;
+	private final List<CPSignature> methodSignature = new ArrayList<>();
+	private final IntList methodExceptionNumber = new IntList();
+	private final List<CPClass> methodExceptionClasses = new ArrayList<>();
+
+	private int[] codeHeaders;
+	private final IntList codeMaxStack = new IntList();
+	private final IntList codeMaxLocals = new IntList();
+	private final IntList codeHandlerCount = new IntList();
+	private final List codeHandlerStartP = new ArrayList();
+	private final List codeHandlerEndPO = new ArrayList();
+	private final List codeHandlerCatchPO = new ArrayList();
+	private final List<CPClass> codeHandlerClass = new ArrayList<>();
+	private final List<Long> codeFlags = new ArrayList<>();
+	private int[] code_attr_calls;
+	private final IntList codeLineNumberTableN = new IntList();
+	private final List codeLineNumberTableBciP = new ArrayList();
+	private final IntList codeLineNumberTableLine = new IntList();
+	private final IntList codeLocalVariableTableN = new IntList();
+	private final List codeLocalVariableTableBciP = new ArrayList();
+	private final List codeLocalVariableTableSpanO = new ArrayList();
+	private final List<ConstantPoolEntry> codeLocalVariableTableNameRU = new ArrayList<>();
+	private final List<ConstantPoolEntry> codeLocalVariableTableTypeRS = new ArrayList<>();
+	private final IntList codeLocalVariableTableSlot = new IntList();
+	private final IntList codeLocalVariableTypeTableN = new IntList();
+	private final List codeLocalVariableTypeTableBciP = new ArrayList();
+	private final List codeLocalVariableTypeTableSpanO = new ArrayList();
+	private final List<ConstantPoolEntry> codeLocalVariableTypeTableNameRU = new ArrayList<>();
+	private final List<ConstantPoolEntry> codeLocalVariableTypeTableTypeRS = new ArrayList<>();
+	private final IntList codeLocalVariableTypeTableSlot = new IntList();
+
+	private final MetadataBandGroup class_RVA_bands;
+	private final MetadataBandGroup class_RIA_bands;
+	private final MetadataBandGroup field_RVA_bands;
+	private final MetadataBandGroup field_RIA_bands;
+	private final MetadataBandGroup method_RVA_bands;
+	private final MetadataBandGroup method_RIA_bands;
+	private final MetadataBandGroup method_RVPA_bands;
+	private final MetadataBandGroup method_RIPA_bands;
+	private final MetadataBandGroup method_AD_bands;
+
+	private final List<NewAttributeBands> classAttributeBands = new ArrayList<>();
+	private final List<NewAttributeBands> methodAttributeBands = new ArrayList<>();
+	private final List<NewAttributeBands> fieldAttributeBands = new ArrayList<>();
+	private final List<NewAttributeBands> codeAttributeBands = new ArrayList<>();
+
+	private final List<Long> tempFieldFlags = new ArrayList<>();
+	private final List<CPNameAndType> tempFieldDesc = new ArrayList<>();
+	private final List<Long> tempMethodFlags = new ArrayList<>();
+	private final List<CPNameAndType> tempMethodDesc = new ArrayList<>();
+	private TempParamAnnotation tempMethodRVPA;
+	private TempParamAnnotation tempMethodRIPA;
+
+	private boolean anySyntheticClasses = false;
+	private boolean anySyntheticFields = false;
+	private boolean anySyntheticMethods = false;
+	private final Segment segment;
+
+	private final Map<CPClass, Set<CPClass>> classReferencesInnerClass = new HashMap<>();
+	private final boolean stripDebug;
+
+	private int index = 0;
+
+	private int numMethodArgs = 0;
+	private int[] class_InnerClasses_N;
+	private CPClass[] class_InnerClasses_RC;
+	private int[] class_InnerClasses_F;
+	private List<CPClass> classInnerClassesOuterRCN;
+	private List<CPUTF8> classInnerClassesNameRUN;
+
+	public ClassBands(final Segment segment, final int numClasses, final int effort, final boolean stripDebug)
+			throws IOException {
+		super(effort, segment.getSegmentHeader());
+		this.stripDebug = stripDebug;
+		this.segment = segment;
+		this.cpBands = segment.getCpBands();
+		this.attrBands = segment.getAttrBands();
+		class_this = new CPClass[numClasses];
+		class_super = new CPClass[numClasses];
+		class_interface_count = new int[numClasses];
+		class_interface = new CPClass[numClasses][];
+		class_field_count = new int[numClasses];
+		class_method_count = new int[numClasses];
+		field_descr = new CPNameAndType[numClasses][];
+		field_flags = new long[numClasses][];
+		method_descr = new CPNameAndType[numClasses][];
+		method_flags = new long[numClasses][];
+		for (int i = 0; i < numClasses; i++) {
+			field_flags[i] = new long[0];
+			method_flags[i] = new long[0];
+		}
+		// minor_versions = new int[numClasses];
+		major_versions = new int[numClasses];
+		class_flags = new long[numClasses];
+
+		class_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
+		class_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_CLASS, cpBands, segmentHeader, effort);
+		field_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
+		field_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_FIELD, cpBands, segmentHeader, effort);
+		method_RVA_bands = new MetadataBandGroup("RVA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
+				effort);
+		method_RIA_bands = new MetadataBandGroup("RIA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
+				effort);
+		method_RVPA_bands = new MetadataBandGroup("RVPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
+				effort);
+		method_RIPA_bands = new MetadataBandGroup("RIPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader,
+				effort);
+		method_AD_bands = new MetadataBandGroup("AD", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
+
+		createNewAttributeBands();
+	}
+
+	private void createNewAttributeBands() throws IOException {
+		for (AttributeDefinition def : attrBands.getClassAttributeLayouts()) {
+			classAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+		}
+		for (AttributeDefinition def : attrBands.getMethodAttributeLayouts()) {
+			methodAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+		}
+		for (AttributeDefinition def : attrBands.getFieldAttributeLayouts()) {
+			fieldAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+		}
+		for (AttributeDefinition def : attrBands.getCodeAttributeLayouts()) {
+			codeAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+		}
+	}
+
+	public void addClass(final int major, int flags, final String className, final String signature,
+			final String superName, final String[] interfaces) {
+		class_this[index] = cpBands.getCPClass(className);
+		class_super[index] = cpBands.getCPClass(superName);
+		class_interface_count[index] = interfaces.length;
+		class_interface[index] = new CPClass[interfaces.length];
+		for (int i = 0; i < interfaces.length; i++) {
+			class_interface[index][i] = cpBands.getCPClass(interfaces[i]);
+		}
+		major_versions[index] = major;
+		class_flags[index] = flags;
+		if (!anySyntheticClasses && ((flags & (1 << 12)) != 0)
+				&& segment.getCurrentClassReader().hasSyntheticAttributes()) {
+			cpBands.addCPUtf8("Synthetic");
+			anySyntheticClasses = true;
+		}
+		if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
+			flags = flags & ~Opcodes.ACC_DEPRECATED;
+			flags = flags | (1 << 20);
+		}
+		if (signature != null) {
+			class_flags[index] |= (1 << 19);
+			classSignature.add(cpBands.getCPSignature(signature));
+		}
+	}
+
+	public void currentClassReferencesInnerClass(final CPClass inner) {
+		if (!(index >= class_this.length)) {
+			final CPClass currentClass = class_this[index];
+			if (currentClass != null && !currentClass.equals(inner)
+					&& !isInnerClassOf(currentClass.toString(), inner)) {
+				Set<CPClass> referencedInnerClasses = classReferencesInnerClass.get(currentClass);
+				if (referencedInnerClasses == null) {
+					referencedInnerClasses = new HashSet<>();
+					classReferencesInnerClass.put(currentClass, referencedInnerClasses);
+				}
+				referencedInnerClasses.add(inner);
+			}
+		}
+	}
+
+	private boolean isInnerClassOf(final String possibleInner, final CPClass possibleOuter) {
+		if (isInnerClass(possibleInner)) {
+			final String superClassName = possibleInner.substring(0, possibleInner.lastIndexOf('$'));
+			if (superClassName.equals(possibleOuter.toString())) {
+				return true;
+			}
+			return isInnerClassOf(superClassName, possibleOuter);
+		}
+		return false;
+	}
+
+	private boolean isInnerClass(final String possibleInner) {
+		return possibleInner.indexOf('$') != -1;
+	}
+
+	public void addField(int flags, final String name, final String desc, final String signature, final Object value) {
+		flags = flags & 0xFFFF;
+		tempFieldDesc.add(cpBands.getCPNameAndType(name, desc));
+		if (signature != null) {
+			fieldSignature.add(cpBands.getCPSignature(signature));
+			flags |= (1 << 19);
+		}
+		if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
+			flags = flags & ~Opcodes.ACC_DEPRECATED;
+			flags = flags | (1 << 20);
+		}
+		if (value != null) {
+			fieldConstantValueKQ.add(cpBands.getConstant(value));
+			flags |= (1 << 17);
+		}
+		if (!anySyntheticFields && ((flags & (1 << 12)) != 0)
+				&& segment.getCurrentClassReader().hasSyntheticAttributes()) {
+			cpBands.addCPUtf8("Synthetic");
+			anySyntheticFields = true;
+		}
+		tempFieldFlags.add(Long.valueOf(flags));
+	}
+
+	/**
+	 * 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
+	 * while classes were being read.
+	 */
+	public void finaliseBands() {
+		final int defaultMajorVersion = segmentHeader.getDefaultMajorVersion();
+		for (int i = 0; i < class_flags.length; i++) {
+			final int major = major_versions[i];
+			if (major != defaultMajorVersion) {
+				class_flags[i] |= 1 << 24;
+				classFileVersionMajor.add(major);
+				classFileVersionMinor.add(0);
+			}
+		}
+		// Calculate code headers
+		codeHeaders = new int[codeHandlerCount.size()];
+		int removed = 0;
+		for (int i = 0; i < codeHeaders.length; i++) {
+			final int numHandlers = codeHandlerCount.get(i - removed);
+			final int maxLocals = codeMaxLocals.get(i - removed);
+			final int maxStack = codeMaxStack.get(i - removed);
+			if (numHandlers == 0) {
+				final int header = maxLocals * 12 + maxStack + 1;
+				if (header < 145 && maxStack < 12) {
+					codeHeaders[i] = header;
+				}
+			} else if (numHandlers == 1) {
+				final int header = maxLocals * 8 + maxStack + 145;
+				if (header < 209 && maxStack < 8) {
+					codeHeaders[i] = header;
+				}
+			} else if (numHandlers == 2) {
+				final int header = maxLocals * 7 + maxStack + 209;
+				if (header < 256 && maxStack < 7) {
+					codeHeaders[i] = header;
+				}
+			}
+			if (codeHeaders[i] != 0) { // Remove the redundant values from
+										// codeHandlerCount, codeMaxLocals and
+										// codeMaxStack
+				codeHandlerCount.remove(i - removed);
+				codeMaxLocals.remove(i - removed);
+				codeMaxStack.remove(i - removed);
+				removed++;
+			} else if (!segment.getSegmentHeader().have_all_code_flags()) {
+				codeFlags.add(Long.valueOf(0));
+			}
+		}
+
+		// Compute any required IcLocals
+		final IntList innerClassesN = new IntList();
+		final List<IcTuple> icLocal = new ArrayList<>();
+		for (int i = 0; i < class_this.length; i++) {
+			final CPClass cpClass = class_this[i];
+			final Set<CPClass> referencedInnerClasses = classReferencesInnerClass.get(cpClass);
+			if (referencedInnerClasses != null) {
+				int innerN = 0;
+				final List<IcTuple> innerClasses = segment.getIcBands().getInnerClassesForOuter(cpClass.toString());
+				if (innerClasses != null) {
+					for (IcTuple element : innerClasses) {
+						referencedInnerClasses.remove(element.C);
+					}
+				}
+				for (CPClass inner : referencedInnerClasses) {
+					final IcTuple icTuple = segment.getIcBands().getIcTuple(inner);
+					if (icTuple != null && !icTuple.isAnonymous()) {
+						// should transmit an icLocal entry
+						icLocal.add(icTuple);
+						innerN++;
+					}
+				}
+				if (innerN != 0) {
+					innerClassesN.add(innerN);
+					class_flags[i] |= (1 << 23);
+				}
+			}
+		}
+		class_InnerClasses_N = innerClassesN.toArray();
+		class_InnerClasses_RC = new CPClass[icLocal.size()];
+		class_InnerClasses_F = new int[icLocal.size()];
+		classInnerClassesOuterRCN = new ArrayList<>();
+		classInnerClassesNameRUN = new ArrayList<>();
+		for (int i = 0; i < class_InnerClasses_RC.length; i++) {
+			final IcTuple icTuple = icLocal.get(i);
+			class_InnerClasses_RC[i] = (icTuple.C);
+			if (icTuple.C2 == null && icTuple.N == null) {
+				class_InnerClasses_F[i] = 0;
+			} else {
+				if (icTuple.F == 0) {
+					class_InnerClasses_F[i] = 0x00010000;
+				} else {
+					class_InnerClasses_F[i] = icTuple.F;
+				}
+				classInnerClassesOuterRCN.add(icTuple.C2);
+				classInnerClassesNameRUN.add(icTuple.N);
+			}
+		}
+		// Calculate any backwards calls from metadata bands
+		final IntList classAttrCalls = new IntList();
+		final IntList fieldAttrCalls = new IntList();
+		final IntList methodAttrCalls = new IntList();
+		final IntList codeAttrCalls = new IntList();
+
+		if (class_RVA_bands.hasContent()) {
+			classAttrCalls.add(class_RVA_bands.numBackwardsCalls());
+		}
+		if (class_RIA_bands.hasContent()) {
+			classAttrCalls.add(class_RIA_bands.numBackwardsCalls());
+		}
+		if (field_RVA_bands.hasContent()) {
+			fieldAttrCalls.add(field_RVA_bands.numBackwardsCalls());
+		}
+		if (field_RIA_bands.hasContent()) {
+			fieldAttrCalls.add(field_RIA_bands.numBackwardsCalls());
+		}
+		if (method_RVA_bands.hasContent()) {
+			methodAttrCalls.add(method_RVA_bands.numBackwardsCalls());
+		}
+		if (method_RIA_bands.hasContent()) {
+			methodAttrCalls.add(method_RIA_bands.numBackwardsCalls());
+		}
+		if (method_RVPA_bands.hasContent()) {
+			methodAttrCalls.add(method_RVPA_bands.numBackwardsCalls());
+		}
+		if (method_RIPA_bands.hasContent()) {
+			methodAttrCalls.add(method_RIPA_bands.numBackwardsCalls());
+		}
+		if (method_AD_bands.hasContent()) {
+			methodAttrCalls.add(method_AD_bands.numBackwardsCalls());
+		}
+
+		// Sort non-predefined attribute bands
+		final Comparator<NewAttributeBands> comparator = (arg0, arg1) -> arg0.getFlagIndex() - arg1.getFlagIndex();
+		classAttributeBands.sort(comparator);
+		methodAttributeBands.sort(comparator);
+		fieldAttributeBands.sort(comparator);
+		codeAttributeBands.sort(comparator);
+
+		for (NewAttributeBands bands : classAttributeBands) {
+			if (bands.isUsedAtLeastOnce()) {
+				for (int backwardsCallCount : bands.numBackwardsCalls()) {
+					classAttrCalls.add(backwardsCallCount);
+				}
+			}
+		}
+		for (NewAttributeBands bands : methodAttributeBands) {
+			if (bands.isUsedAtLeastOnce()) {
+				for (int backwardsCallCount : bands.numBackwardsCalls()) {
+					methodAttrCalls.add(backwardsCallCount);
+				}
+			}
+		}
+		for (NewAttributeBands bands : fieldAttributeBands) {
+			if (bands.isUsedAtLeastOnce()) {
+				for (int backwardsCallCount : bands.numBackwardsCalls()) {
+					fieldAttrCalls.add(backwardsCallCount);
+				}
+			}
+		}
+		for (NewAttributeBands bands : codeAttributeBands) {
+			if (bands.isUsedAtLeastOnce()) {
+				for (int backwardsCallCount : bands.numBackwardsCalls()) {
+					codeAttrCalls.add(backwardsCallCount);
+				}
+			}
+		}
+
+		class_attr_calls = classAttrCalls.toArray();
+		field_attr_calls = fieldAttrCalls.toArray();
+		method_attr_calls = methodAttrCalls.toArray();
+		code_attr_calls = codeAttrCalls.toArray();
+	}
+
+	@Override
+	public void pack(final OutputStream out) throws IOException, Pack200Exception {
+		PackingUtils.log("Writing class bands...");
+
+		byte[] encodedBand = encodeBandInt("class_this", getInts(class_this), Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_this[" + class_this.length + "]");
+
+		encodedBand = encodeBandInt("class_super", getInts(class_super), Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_super[" + class_super.length + "]");
+
+		encodedBand = encodeBandInt("class_interface_count", class_interface_count, Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface_count["
+				+ class_interface_count.length + "]");
+
+		final int totalInterfaces = sum(class_interface_count);
+		final int[] classInterface = new int[totalInterfaces];
+		int k = 0;
+		for (CPClass[] element : class_interface) {
+			if (element != null) {
+				for (final CPClass cpClass : element) {
+					classInterface[k] = cpClass.getIndex();
+					k++;
+				}
+			}
+		}
+
+		encodedBand = encodeBandInt("class_interface", classInterface, Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_interface[" + classInterface.length + "]");
+
+		encodedBand = encodeBandInt("class_field_count", class_field_count, Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from class_field_count[" + class_field_count.length + "]");
+
+		encodedBand = encodeBandInt("class_method_count", class_method_count, Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils.log(
+				"Wrote " + encodedBand.length + " bytes from class_method_count[" + class_method_count.length + "]");
+
+		final int totalFields = sum(class_field_count);
+		final int[] fieldDescr = new int[totalFields];
+		k = 0;
+		for (int i = 0; i < index; i++) {
+			for (int j = 0; j < field_descr[i].length; j++) {
+				final CPNameAndType descr = field_descr[i][j];
+				fieldDescr[k] = descr.getIndex();
+				k++;
+			}
+		}
+
+		encodedBand = encodeBandInt("field_descr", fieldDescr, Codec.DELTA5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_descr[" + fieldDescr.length + "]");
+
+		writeFieldAttributeBands(out);
+
+		final int totalMethods = sum(class_method_count);
+		final int[] methodDescr = new int[totalMethods];
+		k = 0;
+		for (int i = 0; i < index; i++) {
+			for (int j = 0; j < method_descr[i].length; j++) {
+				final CPNameAndType descr = method_descr[i][j];
+				methodDescr[k] = descr.getIndex();
+				k++;
+			}
+		}
+
+		encodedBand = encodeBandInt("method_descr", methodDescr, Codec.MDELTA5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_descr[" + methodDescr.length + "]");
+
+		writeMethodAttributeBands(out);
+		writeClassAttributeBands(out);
+		writeCodeBands(out);
+	}
+
+	private int sum(final int[] ints) {
+		int sum = 0;
+		for (int j : ints) {
+			sum += j;
+		}
+		return sum;
+	}
+
+	private void writeFieldAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
+		byte[] encodedBand = encodeFlags("field_flags", field_flags, Codec.UNSIGNED5, Codec.UNSIGNED5,
+				segmentHeader.have_field_flags_hi());
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from field_flags[" + field_flags.length + "]");
+
+		// *field_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
+		// *field_attr_indexes :UNSIGNED5 [SUM(*field_attr_count)]
+		encodedBand = encodeBandInt("field_attr_calls", field_attr_calls, Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from field_attr_calls[" + field_attr_calls.length + "]");
+
+		encodedBand = encodeBandInt("fieldConstantValueKQ", cpEntryListToArray(fieldConstantValueKQ), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldConstantValueKQ["
+				+ fieldConstantValueKQ.size() + "]");
+
+		encodedBand = encodeBandInt("fieldSignature", cpEntryListToArray(fieldSignature), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from fieldSignature[" + fieldSignature.size() + "]");
+
+		field_RVA_bands.pack(out);
+		field_RIA_bands.pack(out);
+		for (NewAttributeBands bands : fieldAttributeBands) {
+			bands.pack(out);
+		}
+	}
+
+	private void writeMethodAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
+		byte[] encodedBand = encodeFlags("method_flags", method_flags, Codec.UNSIGNED5, Codec.UNSIGNED5,
+				segmentHeader.have_method_flags_hi());
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from method_flags[" + method_flags.length + "]");
+
+		// *method_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
+		// *method_attr_indexes :UNSIGNED5 [SUM(*method_attr_count)]
+		encodedBand = encodeBandInt("method_attr_calls", method_attr_calls, Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from method_attr_calls[" + method_attr_calls.length + "]");
+
+		encodedBand = encodeBandInt("methodExceptionNumber", methodExceptionNumber.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionNumber["
+				+ methodExceptionNumber.size() + "]");
+
+		encodedBand = encodeBandInt("methodExceptionClasses", cpEntryListToArray(methodExceptionClasses),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodExceptionClasses["
+				+ methodExceptionClasses.size() + "]");
+
+		encodedBand = encodeBandInt("methodSignature", cpEntryListToArray(methodSignature), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from methodSignature[" + methodSignature.size() + "]");
+
+		method_RVA_bands.pack(out);
+		method_RIA_bands.pack(out);
+		method_RVPA_bands.pack(out);
+		method_RIPA_bands.pack(out);
+		method_AD_bands.pack(out);
+		for (NewAttributeBands bands : methodAttributeBands) {
+			bands.pack(out);
+		}
+	}
+
+	private void writeClassAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
+		byte[] encodedBand = encodeFlags("class_flags", class_flags, Codec.UNSIGNED5, Codec.UNSIGNED5,
+				segmentHeader.have_class_flags_hi());
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_flags[" + class_flags.length + "]");
+
+		// These bands are not needed, but could be used to reduce the size of
+		// the archive if there are enough different non-standard attributes
+		// defined that segmentHeader.have_class_flags_hi() is true. The same
+		// applies to method_attr_count, field_attr_count, code_attr_count etc.
+
+		// *class_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
+		// *class_attr_indexes :UNSIGNED5 [SUM(*class_attr_count)]
+
+		encodedBand = encodeBandInt("class_attr_calls", class_attr_calls, Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from class_attr_calls[" + class_attr_calls.length + "]");
+
+		encodedBand = encodeBandInt("classSourceFile", cpEntryOrNullListToArray(classSourceFile), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from classSourceFile[" + classSourceFile.size() + "]");
+
+		encodedBand = encodeBandInt("class_enclosing_method_RC", cpEntryListToArray(classEnclosingMethodClass),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_enclosing_method_RC["
+				+ classEnclosingMethodClass.size() + "]");
+
+		encodedBand = encodeBandInt("class_EnclosingMethod_RDN", cpEntryOrNullListToArray(classEnclosingMethodDesc),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_EnclosingMethod_RDN["
+				+ classEnclosingMethodDesc.size() + "]");
+
+		encodedBand = encodeBandInt("class_Signature_RS", cpEntryListToArray(classSignature), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from class_Signature_RS[" + classSignature.size() + "]");
+
+		class_RVA_bands.pack(out);
+		class_RIA_bands.pack(out);
+
+		encodedBand = encodeBandInt("class_InnerClasses_N", class_InnerClasses_N, Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_N["
+				+ class_InnerClasses_N.length + "]");
+
+		encodedBand = encodeBandInt("class_InnerClasses_RC", getInts(class_InnerClasses_RC), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_RC["
+				+ class_InnerClasses_RC.length + "]");
+
+		encodedBand = encodeBandInt("class_InnerClasses_F", class_InnerClasses_F, Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_F["
+				+ class_InnerClasses_F.length + "]");
+
+		encodedBand = encodeBandInt("class_InnerClasses_outer_RCN", cpEntryOrNullListToArray(classInnerClassesOuterRCN),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_outer_RCN["
+				+ classInnerClassesOuterRCN.size() + "]");
+
+		encodedBand = encodeBandInt("class_InnerClasses_name_RUN", cpEntryOrNullListToArray(classInnerClassesNameRUN),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from class_InnerClasses_name_RUN["
+				+ classInnerClassesNameRUN.size() + "]");
+
+		encodedBand = encodeBandInt("classFileVersionMinor", classFileVersionMinor.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from classFileVersionMinor["
+				+ classFileVersionMinor.size() + "]");
+
+		encodedBand = encodeBandInt("classFileVersionMajor", classFileVersionMajor.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from classFileVersionMajor["
+				+ classFileVersionMajor.size() + "]");
+
+		for (NewAttributeBands classAttributeBand : classAttributeBands) {
+			classAttributeBand.pack(out);
+		}
+	}
+
+	private int[] getInts(final CPClass[] cpClasses) {
+		final int[] ints = new int[cpClasses.length];
+		for (int i = 0; i < ints.length; i++) {
+			if (cpClasses[i] != null) {
+				ints[i] = cpClasses[i].getIndex();
+			}
+		}
+		return ints;
+	}
+
+	private void writeCodeBands(final OutputStream out) throws IOException, Pack200Exception {
+		byte[] encodedBand = encodeBandInt("codeHeaders", codeHeaders, Codec.BYTE1);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeHeaders[" + codeHeaders.length + "]");
+
+		encodedBand = encodeBandInt("codeMaxStack", codeMaxStack.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxStack[" + codeMaxStack.size() + "]");
+
+		encodedBand = encodeBandInt("codeMaxLocals", codeMaxLocals.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeMaxLocals[" + codeMaxLocals.size() + "]");
+
+		encodedBand = encodeBandInt("codeHandlerCount", codeHandlerCount.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from codeHandlerCount[" + codeHandlerCount.size() + "]");
+
+		encodedBand = encodeBandInt("codeHandlerStartP", integerListToArray(codeHandlerStartP), Codec.BCI5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from codeHandlerStartP[" + codeHandlerStartP.size() + "]");
+
+		encodedBand = encodeBandInt("codeHandlerEndPO", integerListToArray(codeHandlerEndPO), Codec.BRANCH5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from codeHandlerEndPO[" + codeHandlerEndPO.size() + "]");
+
+		encodedBand = encodeBandInt("codeHandlerCatchPO", integerListToArray(codeHandlerCatchPO), Codec.BRANCH5);
+		out.write(encodedBand);
+		PackingUtils.log(
+				"Wrote " + encodedBand.length + " bytes from codeHandlerCatchPO[" + codeHandlerCatchPO.size() + "]");
+
+		encodedBand = encodeBandInt("codeHandlerClass", cpEntryOrNullListToArray(codeHandlerClass), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils
+				.log("Wrote " + encodedBand.length + " bytes from codeHandlerClass[" + codeHandlerClass.size() + "]");
+
+		writeCodeAttributeBands(out);
+	}
+
+	private void writeCodeAttributeBands(final OutputStream out) throws IOException, Pack200Exception {
+		byte[] encodedBand = encodeFlags("codeFlags", longListToArray(codeFlags), Codec.UNSIGNED5, Codec.UNSIGNED5,
+				segmentHeader.have_code_flags_hi());
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from codeFlags[" + codeFlags.size() + "]");
+
+		// *code_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
+		// *code_attr_indexes :UNSIGNED5 [SUM(*code_attr_count)]
+		encodedBand = encodeBandInt("code_attr_calls", code_attr_calls, Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_attr_calls[" + code_attr_calls.length + "]");
+
+		encodedBand = encodeBandInt("code_LineNumberTable_N", codeLineNumberTableN.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_N["
+				+ codeLineNumberTableN.size() + "]");
+
+		encodedBand = encodeBandInt("code_LineNumberTable_bci_P", integerListToArray(codeLineNumberTableBciP),
+				Codec.BCI5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_bci_P["
+				+ codeLineNumberTableBciP.size() + "]");
+
+		encodedBand = encodeBandInt("code_LineNumberTable_line", codeLineNumberTableLine.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LineNumberTable_line["
+				+ codeLineNumberTableLine.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTable_N", codeLocalVariableTableN.toArray(), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_N["
+				+ codeLocalVariableTableN.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTable_bci_P", integerListToArray(codeLocalVariableTableBciP),
+				Codec.BCI5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_bci_P["
+				+ codeLocalVariableTableBciP.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTable_span_O", integerListToArray(codeLocalVariableTableSpanO),
+				Codec.BRANCH5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_span_O["
+				+ codeLocalVariableTableSpanO.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTable_name_RU", cpEntryListToArray(codeLocalVariableTableNameRU),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_name_RU["
+				+ codeLocalVariableTableNameRU.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTable_type_RS", cpEntryListToArray(codeLocalVariableTableTypeRS),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_type_RS["
+				+ codeLocalVariableTableTypeRS.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTable_slot", codeLocalVariableTableSlot.toArray(),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTable_slot["
+				+ codeLocalVariableTableSlot.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTypeTable_N", codeLocalVariableTypeTableN.toArray(),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_N["
+				+ codeLocalVariableTypeTableN.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTypeTable_bci_P",
+				integerListToArray(codeLocalVariableTypeTableBciP), Codec.BCI5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_bci_P["
+				+ codeLocalVariableTypeTableBciP.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTypeTable_span_O",
+				integerListToArray(codeLocalVariableTypeTableSpanO), Codec.BRANCH5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_span_O["
+				+ codeLocalVariableTypeTableSpanO.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTypeTable_name_RU",
+				cpEntryListToArray(codeLocalVariableTypeTableNameRU), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_name_RU["
+				+ codeLocalVariableTypeTableNameRU.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTypeTable_type_RS",
+				cpEntryListToArray(codeLocalVariableTypeTableTypeRS), Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_type_RS["
+				+ codeLocalVariableTypeTableTypeRS.size() + "]");
+
+		encodedBand = encodeBandInt("code_LocalVariableTypeTable_slot", codeLocalVariableTypeTableSlot.toArray(),
+				Codec.UNSIGNED5);
+		out.write(encodedBand);
+		PackingUtils.log("Wrote " + encodedBand.length + " bytes from code_LocalVariableTypeTable_slot["
+				+ codeLocalVariableTypeTableSlot.size() + "]");
+
+		for (NewAttributeBands bands : codeAttributeBands) {
+			bands.pack(out);
+		}
+	}
+
+	public void addMethod(int flags, final String name, final String desc, final String signature,
+			final String[] exceptions) {
+		final CPNameAndType nt = cpBands.getCPNameAndType(name, desc);
+		tempMethodDesc.add(nt);
+		if (signature != null) {
+			methodSignature.add(cpBands.getCPSignature(signature));
+			flags |= (1 << 19);
+		}
+		if (exceptions != null) {
+			methodExceptionNumber.add(exceptions.length);
+			for (String exception : exceptions) {
+				methodExceptionClasses.add(cpBands.getCPClass(exception));
+			}
+			flags |= (1 << 18);
+		}
+		if ((flags & Opcodes.ACC_DEPRECATED) != 0) { // ASM uses (1<<17) flag for deprecated
+			flags = flags & ~Opcodes.ACC_DEPRECATED;
+			flags = flags | (1 << 20);
+		}
+		tempMethodFlags.add(Long.valueOf(flags));
+		numMethodArgs = countArgs(desc);
+		if (!anySyntheticMethods && ((flags & (1 << 12)) != 0)
+				&& segment.getCurrentClassReader().hasSyntheticAttributes()) {
+			cpBands.addCPUtf8("Synthetic");
+			anySyntheticMethods = true;
+		}
+	}
+
+	public void endOfMethod() {
+		if (tempMethodRVPA != null) {
+			method_RVPA_bands.addParameterAnnotation(tempMethodRVPA.numParams, tempMethodRVPA.annoN,
+					tempMethodRVPA.pairN, tempMethodRVPA.typeRS, tempMethodRVPA.nameRU, tempMethodRVPA.tags,
+					tempMethodRVPA.values, tempMethodRVPA.caseArrayN, tempMethodRVPA.nestTypeRS,
+					tempMethodRVPA.nestNameRU, tempMethodRVPA.nestPairN);
+			tempMethodRVPA = null;
+		}
+		if (tempMethodRIPA != null) {
+			method_RIPA_bands.addParameterAnnotation(tempMethodRIPA.numParams, tempMethodRIPA.annoN,
+					tempMethodRIPA.pairN, tempMethodRIPA.typeRS, tempMethodRIPA.nameRU, tempMethodRIPA.tags,
+					tempMethodRIPA.values, tempMethodRIPA.caseArrayN, tempMethodRIPA.nestTypeRS,
+					tempMethodRIPA.nestNameRU, tempMethodRIPA.nestPairN);
+			tempMethodRIPA = null;
+		}
+		if (codeFlags.size() > 0) {
+			final long latestCodeFlag = codeFlags.get(codeFlags.size() - 1).longValue();
+			final int latestLocalVariableTableN = codeLocalVariableTableN.get(codeLocalVariableTableN.size() - 1);
+			if (latestCodeFlag == (1 << 2) && latestLocalVariableTableN == 0) {
+				codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
+				codeFlags.remove(codeFlags.size() - 1);
+				codeFlags.add(Long.valueOf(0));
+			}
+		}
+	}
+
+	protected static int countArgs(final String descriptor) {
+		final int bra = descriptor.indexOf('(');
+		final int ket = descriptor.indexOf(')');
+		if (bra == -1 || ket == -1 || ket < bra) {
+			throw new IllegalArgumentException("No arguments");
+		}
+
+		boolean inType = false;
+		boolean consumingNextType = false;
+		int count = 0;
+		for (int i = bra + 1; i < ket; i++) {
+			final char charAt = descriptor.charAt(i);
+			if (inType && charAt == ';') {
+				inType = false;
+				consumingNextType = false;
+			} else if (!inType && charAt == 'L') {
+				inType = true;
+				count++;
+			} else if (charAt == '[') {
+				consumingNextType = true;
+			} else if (inType) {
+				// NOP
+			} else if (consumingNextType) {
+				count++;
+				consumingNextType = false;
+			} else if (charAt == 'D' || charAt == 'J') {
+				count += 2;
+			} else {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	public void endOfClass() { // All the data for the current class has been
+								// read
+		final int numFields = tempFieldDesc.size();
+		class_field_count[index] = numFields;
+		field_descr[index] = new CPNameAndType[numFields];
+		field_flags[index] = new long[numFields];
+		for (int i = 0; i < numFields; i++) {
+			field_descr[index][i] = tempFieldDesc.get(i);
+			field_flags[index][i] = tempFieldFlags.get(i).longValue();
+		}
+		final int numMethods = tempMethodDesc.size();
+		class_method_count[index] = numMethods;
+		method_descr[index] = new CPNameAndType[numMethods];
+		method_flags[index] = new long[numMethods];
+		for (int i = 0; i < numMethods; i++) {
+			method_descr[index][i] = tempMethodDesc.get(i);
+			method_flags[index][i] = tempMethodFlags.get(i).longValue();
+		}
+		tempFieldDesc.clear();
+		tempFieldFlags.clear();
+		tempMethodDesc.clear();
+		tempMethodFlags.clear();
+		index++;
+	}
+
+	public void addSourceFile(final String source) {
+		String implicitSourceFileName = class_this[index].toString();
+		if (implicitSourceFileName.indexOf('$') != -1) {
+			implicitSourceFileName = implicitSourceFileName.substring(0, implicitSourceFileName.indexOf('$'));
+		}
+		implicitSourceFileName = implicitSourceFileName.substring(implicitSourceFileName.lastIndexOf('/') + 1)
+				+ ".java";
+		if (source.equals(implicitSourceFileName)) {
+			classSourceFile.add(null);
+		} else {
+			classSourceFile.add(cpBands.getCPUtf8(source));
+		}
+		class_flags[index] |= (1 << 17);
+	}
+
+	public void addEnclosingMethod(final String owner, final String name, final String desc) {
+		class_flags[index] |= (1 << 18);
+		classEnclosingMethodClass.add(cpBands.getCPClass(owner));
+		classEnclosingMethodDesc.add(name == null ? null : cpBands.getCPNameAndType(name, desc));
+	}
+
+	public void addClassAttribute(final NewAttribute attribute) {
+		// TODO: backwards calls
+		final String attributeName = attribute.type;
+		for (NewAttributeBands bands : classAttributeBands) {
+			if (bands.getAttributeName().equals(attributeName)) {
+				bands.addAttribute(attribute);
+				final int flagIndex = bands.getFlagIndex();
+				class_flags[index] |= (1 << flagIndex);
+				return;
+			}
+		}
+		throw new IllegalArgumentException("No suitable definition for " + attributeName);
+	}
+
+	public void addFieldAttribute(final NewAttribute attribute) {
+		final String attributeName = attribute.type;
+		for (NewAttributeBands bands : fieldAttributeBands) {
+			if (bands.getAttributeName().equals(attributeName)) {
+				bands.addAttribute(attribute);
+				final int flagIndex = bands.getFlagIndex();
+				final Long flags = tempFieldFlags.remove(tempFieldFlags.size() - 1);
+				tempFieldFlags.add(Long.valueOf(flags.longValue() | (1 << flagIndex)));
+				return;
+			}
+		}
+		throw new IllegalArgumentException("No suitable definition for " + attributeName);
+	}
+
+	public void addMethodAttribute(final NewAttribute attribute) {
+		final String attributeName = attribute.type;
+		for (NewAttributeBands bands : methodAttributeBands) {
+			if (bands.getAttributeName().equals(attributeName)) {
+				bands.addAttribute(attribute);
+				final int flagIndex = bands.getFlagIndex();
+				final Long flags = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+				tempMethodFlags.add(Long.valueOf(flags.longValue() | (1 << flagIndex)));
+				return;
+			}
+		}
+		throw new IllegalArgumentException("No suitable definition for " + attributeName);
+	}
+
+	public void addCodeAttribute(final NewAttribute attribute) {
+		final String attributeName = attribute.type;
+		for (NewAttributeBands bands : codeAttributeBands) {
+			if (bands.getAttributeName().equals(attributeName)) {
+				bands.addAttribute(attribute);
+				final int flagIndex = bands.getFlagIndex();
+				final Long flags = codeFlags.remove(codeFlags.size() - 1);
+				codeFlags.add(Long.valueOf(flags.longValue() | (1 << flagIndex)));
+				return;
+			}
+		}
+		throw new IllegalArgumentException("No suitable definition for " + attributeName);
+	}
+
+	public void addMaxStack(final int maxStack, int maxLocals) {
+		final Long latestFlag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+		final Long newFlag = Long.valueOf(latestFlag.intValue() | (1 << 17));
+		tempMethodFlags.add(newFlag);
+		codeMaxStack.add(maxStack);
+		if ((newFlag.longValue() & (1 << 3)) == 0) { // not static
+			maxLocals--; // minus 'this' local
+		}
+		maxLocals -= numMethodArgs;
+		codeMaxLocals.add(maxLocals);
+	}
+
+	public void addCode() {
+		codeHandlerCount.add(0);
+		if (!stripDebug) {
+			codeFlags.add(Long.valueOf(1 << 2));
+			codeLocalVariableTableN.add(0);
+		}
+	}
+
+	public void addHandler(final Label start, final Label end, final Label handler, final String type) {
+		final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
+		codeHandlerCount.add(handlers + 1);
+		codeHandlerStartP.add(start);
+		codeHandlerEndPO.add(end);
+		codeHandlerCatchPO.add(handler);
+		codeHandlerClass.add(type == null ? null : cpBands.getCPClass(type));
+	}
+
+	public void addLineNumber(final int line, final Label start) {
+		final Long latestCodeFlag = codeFlags.get(codeFlags.size() - 1);
+		if ((latestCodeFlag.intValue() & (1 << 1)) == 0) {
+			codeFlags.remove(codeFlags.size() - 1);
+			codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | (1 << 1)));
+			codeLineNumberTableN.add(1);
+		} else {
+			codeLineNumberTableN.increment(codeLineNumberTableN.size() - 1);
+		}
+		codeLineNumberTableLine.add(line);
+		codeLineNumberTableBciP.add(start);
+	}
+
+	public void addLocalVariable(final String name, final String desc, final String signature, final Label start,
+			final Label end, final int indx) {
+		if (signature != null) { // LocalVariableTypeTable attribute
+			final Long latestCodeFlag = codeFlags.get(codeFlags.size() - 1);
+			if ((latestCodeFlag.intValue() & (1 << 3)) == 0) {
+				codeFlags.remove(codeFlags.size() - 1);
+				codeFlags.add(Long.valueOf(latestCodeFlag.intValue() | (1 << 3)));
+				codeLocalVariableTypeTableN.add(1);
+			} else {
+				codeLocalVariableTypeTableN.increment(codeLocalVariableTypeTableN.size() - 1);
+			}
+			codeLocalVariableTypeTableBciP.add(start);
+			codeLocalVariableTypeTableSpanO.add(end);
+			codeLocalVariableTypeTableNameRU.add(cpBands.getCPUtf8(name));
+			codeLocalVariableTypeTableTypeRS.add(cpBands.getCPSignature(signature));
+			codeLocalVariableTypeTableSlot.add(indx);
+		}
+		// LocalVariableTable attribute
+		codeLocalVariableTableN.increment(codeLocalVariableTableN.size() - 1);
+		codeLocalVariableTableBciP.add(start);
+		codeLocalVariableTableSpanO.add(end);
+		codeLocalVariableTableNameRU.add(cpBands.getCPUtf8(name));
+		codeLocalVariableTableTypeRS.add(cpBands.getCPSignature(desc));
+		codeLocalVariableTableSlot.add(indx);
+	}
+
+	public void doBciRenumbering(final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
+		renumberBci(codeLineNumberTableBciP, bciRenumbering, labelsToOffsets);
+		renumberBci(codeLocalVariableTableBciP, bciRenumbering, labelsToOffsets);
+		renumberOffsetBci(codeLocalVariableTableBciP, codeLocalVariableTableSpanO, bciRenumbering, labelsToOffsets);
+		renumberBci(codeLocalVariableTypeTableBciP, bciRenumbering, labelsToOffsets);
+		renumberOffsetBci(codeLocalVariableTypeTableBciP, codeLocalVariableTypeTableSpanO, bciRenumbering,
+				labelsToOffsets);
+		renumberBci(codeHandlerStartP, bciRenumbering, labelsToOffsets);
+		renumberOffsetBci(codeHandlerStartP, codeHandlerEndPO, bciRenumbering, labelsToOffsets);
+		renumberDoubleOffsetBci(codeHandlerStartP, codeHandlerEndPO, codeHandlerCatchPO, bciRenumbering,
+				labelsToOffsets);
+
+		for (NewAttributeBands newAttributeBandSet : classAttributeBands) {
+			newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+		}
+		for (NewAttributeBands newAttributeBandSet : methodAttributeBands) {
+			newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+		}
+		for (NewAttributeBands newAttributeBandSet : fieldAttributeBands) {
+			newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+		}
+		for (NewAttributeBands newAttributeBandSet : codeAttributeBands) {
+			newAttributeBandSet.renumberBci(bciRenumbering, labelsToOffsets);
+		}
+	}
+
+	private void renumberBci(final List<Integer> list, final IntList bciRenumbering,
+			final Map<Label, Integer> labelsToOffsets) {
+		for (int i = list.size() - 1; i >= 0; i--) {
+			final Object label = list.get(i);
+			if (label instanceof Integer) {
+				break;
+			}
+			if (label instanceof Label) {
+				list.remove(i);
+				final Integer bytecodeIndex = labelsToOffsets.get(label);
+				list.add(i, Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue())));
+			}
+		}
+	}
+
+	private void renumberOffsetBci(final List<Integer> relative, final List<Integer> list, final IntList bciRenumbering,
+			final Map<Label, Integer> labelsToOffsets) {
+		for (int i = list.size() - 1; i >= 0; i--) {
+			final Object label = list.get(i);
+			if (label instanceof Integer) {
+				break;
+			}
+			if (label instanceof Label) {
+				list.remove(i);
+				final Integer bytecodeIndex = labelsToOffsets.get(label);
+				final Integer renumberedOffset = Integer
+						.valueOf(bciRenumbering.get(bytecodeIndex.intValue()) - relative.get(i).intValue());
+				list.add(i, renumberedOffset);
+			}
+		}
+	}
+
+	private void renumberDoubleOffsetBci(final List<Integer> relative, final List<Integer> firstOffset, final List<Object> list,
+			final IntList bciRenumbering, final Map<Label, Integer> labelsToOffsets) {
+		// TODO: There's probably a nicer way of doing this...
+		for (int i = list.size() - 1; i >= 0; i--) {
+			final Object label = list.get(i);
+			if (label instanceof Integer) {
+				break;
+			}
+			if (label instanceof Label) {
+				list.remove(i);
+				final Integer bytecodeIndex = labelsToOffsets.get(label);
+				final Integer renumberedOffset = Integer.valueOf(bciRenumbering.get(bytecodeIndex.intValue())
+						- relative.get(i).intValue() - firstOffset.get(i).intValue());
+				list.add(i, renumberedOffset);
+			}
+		}
+	}
+
+	public boolean isAnySyntheticClasses() {
+		return anySyntheticClasses;
+	}
+
+	public boolean isAnySyntheticFields() {
+		return anySyntheticFields;
+	}
+
+	public boolean isAnySyntheticMethods() {
+		return anySyntheticMethods;
+	}
+
+	public void addParameterAnnotation(final int parameter, final String desc, final boolean visible,
+			final List<String> nameRU, final List<String> tags, final List<Object> values,
+			final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
+			final List<Integer> nestPairN) {
+		if (visible) {
+			if (tempMethodRVPA == null) {
+				tempMethodRVPA = new TempParamAnnotation(numMethodArgs);
+				tempMethodRVPA.addParameterAnnotation(parameter, desc, nameRU, tags, values, caseArrayN, nestTypeRS,
+						nestNameRU, nestPairN);
+			}
+			final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+			tempMethodFlags.add(Long.valueOf(flag.longValue() | (1 << 23)));
+		} else {
+			if (tempMethodRIPA == null) {
+				tempMethodRIPA = new TempParamAnnotation(numMethodArgs);
+				tempMethodRIPA.addParameterAnnotation(parameter, desc, nameRU, tags, values, caseArrayN, nestTypeRS,
+						nestNameRU, nestPairN);
+			}
+			final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+			tempMethodFlags.add(Long.valueOf(flag.longValue() | (1 << 24)));
+		}
+	}
+
+	private static class TempParamAnnotation {
+
+		int numParams;
+		int[] annoN;
+		IntList pairN = new IntList();
+		List<String> typeRS = new ArrayList<>();
+		List<String> nameRU = new ArrayList<>();
+		List<String> tags = new ArrayList<>();
+		List<Object> values = new ArrayList<>();
+		List<Integer> caseArrayN = new ArrayList<>();
+		List<String> nestTypeRS = new ArrayList<>();
+		List<String> nestNameRU = new ArrayList<>();
+		List<Integer> nestPairN = new ArrayList<>();
+
+		public TempParamAnnotation(final int numParams) {
+			this.numParams = numParams;
+			annoN = new int[numParams];
+		}
+
+		public void addParameterAnnotation(final int parameter, final String desc, final List<String> nameRU,
+				final List<String> tags, final List<Object> values, final List<Integer> caseArrayN,
+				final List<String> nestTypeRS, final List<String> nestNameRU, final List<Integer> nestPairN) {
+			annoN[parameter]++;
+			typeRS.add(desc);
+			pairN.add(nameRU.size());
+			this.nameRU.addAll(nameRU);
+			this.tags.addAll(tags);
+			this.values.addAll(values);
+			this.caseArrayN.addAll(caseArrayN);
+			this.nestTypeRS.addAll(nestTypeRS);
+			this.nestNameRU.addAll(nestNameRU);
+			this.nestPairN.addAll(nestPairN);
+		}
+	}
+
+	public void addAnnotation(final int context, final String desc, final boolean visible, final List<String> nameRU,
+			final List<String> tags, final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS,
+			final List<String> nestNameRU, final List<Integer> nestPairN) {
+		switch (context) {
+		case MetadataBandGroup.CONTEXT_CLASS:
+			if (visible) {
+				class_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
+						nestPairN);
+				if ((class_flags[index] & (1 << 21)) != 0) {
+					class_RVA_bands.incrementAnnoN();
+				} else {
+					class_RVA_bands.newEntryInAnnoN();
+					class_flags[index] = class_flags[index] | (1 << 21);
+				}
+			} else {
+				class_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
+						nestPairN);
+				if ((class_flags[index] & (1 << 22)) != 0) {
+					class_RIA_bands.incrementAnnoN();
+				} else {
+					class_RIA_bands.newEntryInAnnoN();
+					class_flags[index] = class_flags[index] | (1 << 22);
+				}
+			}
+			break;
+		case MetadataBandGroup.CONTEXT_FIELD:
+			if (visible) {
+				field_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
+						nestPairN);
+				final Long flag = tempFieldFlags.remove(tempFieldFlags.size() - 1);
+				if ((flag.intValue() & (1 << 21)) != 0) {
+					field_RVA_bands.incrementAnnoN();
+				} else {
+					field_RVA_bands.newEntryInAnnoN();
+				}
+				tempFieldFlags.add(Long.valueOf(flag.intValue() | (1 << 21)));
+			} else {
+				field_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
+						nestPairN);
+				final Long flag = tempFieldFlags.remove(tempFieldFlags.size() - 1);
+				if ((flag.intValue() & (1 << 22)) != 0) {
+					field_RIA_bands.incrementAnnoN();
+				} else {
+					field_RIA_bands.newEntryInAnnoN();
+				}
+				tempFieldFlags.add(Long.valueOf(flag.intValue() | (1 << 22)));
+			}
+			break;
+		case MetadataBandGroup.CONTEXT_METHOD:
+			if (visible) {
+				method_RVA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
+						nestPairN);
+				final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+				if ((flag.intValue() & (1 << 21)) != 0) {
+					method_RVA_bands.incrementAnnoN();
+				} else {
+					method_RVA_bands.newEntryInAnnoN();
+				}
+				tempMethodFlags.add(Long.valueOf(flag.intValue() | (1 << 21)));
+			} else {
+				method_RIA_bands.addAnnotation(desc, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
+						nestPairN);
+				final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+				if ((flag.intValue() & (1 << 22)) != 0) {
+					method_RIA_bands.incrementAnnoN();
+				} else {
+					method_RIA_bands.newEntryInAnnoN();
+				}
+				tempMethodFlags.add(Long.valueOf(flag.intValue() | (1 << 22)));
+			}
+			break;
+		}
+	}
+
+	public void addAnnotationDefault(final List<String> nameRU, final List<String> tags, final List<Object> values,
+			final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
+			final List<Integer> nestPairN) {
+		method_AD_bands.addAnnotation(null, nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
+		final Long flag = tempMethodFlags.remove(tempMethodFlags.size() - 1);
+		tempMethodFlags.add(Long.valueOf(flag.longValue() | (1 << 25)));
+	}
+
+	/**
+	 * Remove all entries for the current class
+	 */
+	public void removeCurrentClass() {
+		// Note - this doesn't remove any entries added to the constant pool but
+		// that shouldn't be a problem
+		if ((class_flags[index] & (1 << 17)) != 0) {
+			classSourceFile.remove(classSourceFile.size() - 1);
+		}
+		if ((class_flags[index] & (1 << 18)) != 0) {
+			classEnclosingMethodClass.remove(classEnclosingMethodClass.size() - 1);
+			classEnclosingMethodDesc.remove(classEnclosingMethodDesc.size() - 1);
+		}
+		if ((class_flags[index] & (1 << 19)) != 0) {
+			classSignature.remove(classSignature.size() - 1);
+		}
+		if ((class_flags[index] & (1 << 21)) != 0) {
+			class_RVA_bands.removeLatest();
+		}
+		if ((class_flags[index] & (1 << 22)) != 0) {
+			class_RIA_bands.removeLatest();
+		}
+		for (Long flagsL : tempFieldFlags) {
+			final long flags = flagsL.longValue();
+			if ((flags & (1 << 19)) != 0) {
+				fieldSignature.remove(fieldSignature.size() - 1);
+			}
+			if ((flags & (1 << 17)) != 0) {
+				fieldConstantValueKQ.remove(fieldConstantValueKQ.size() - 1);
+			}
+			if ((flags & (1 << 21)) != 0) {
+				field_RVA_bands.removeLatest();
+			}
+			if ((flags & (1 << 22)) != 0) {
+				field_RIA_bands.removeLatest();
+			}
+		}
+		for (Long flagsL : tempMethodFlags) {
+			final long flags = flagsL.longValue();
+			if ((flags & (1 << 19)) != 0) {
+				methodSignature.remove(methodSignature.size() - 1);
+			}
+			if ((flags & (1 << 18)) != 0) {
+				final int exceptions = methodExceptionNumber.remove(methodExceptionNumber.size() - 1);
+				for (int i = 0; i < exceptions; i++) {
+					methodExceptionClasses.remove(methodExceptionClasses.size() - 1);
+				}
+			}
+			if ((flags & (1 << 17)) != 0) { // has code attribute
+				codeMaxLocals.remove(codeMaxLocals.size() - 1);
+				codeMaxStack.remove(codeMaxStack.size() - 1);
+				final int handlers = codeHandlerCount.remove(codeHandlerCount.size() - 1);
+				for (int i = 0; i < handlers; i++) {
+					final int index = codeHandlerStartP.size() - 1;
+					codeHandlerStartP.remove(index);
+					codeHandlerEndPO.remove(index);
+					codeHandlerCatchPO.remove(index);
+					codeHandlerClass.remove(index);
+				}
+				if (!stripDebug) {
+					final long cdeFlags = codeFlags.remove(codeFlags.size() - 1).longValue();
+					final int numLocalVariables = codeLocalVariableTableN.remove(codeLocalVariableTableN.size() - 1);
+					for (int i = 0; i < numLocalVariables; i++) {
+						final int location = codeLocalVariableTableBciP.size() - 1;
+						codeLocalVariableTableBciP.remove(location);
+						codeLocalVariableTableSpanO.remove(location);
+						codeLocalVariableTableNameRU.remove(location);
+						codeLocalVariableTableTypeRS.remove(location);
+						codeLocalVariableTableSlot.remove(location);
+					}
+					if ((cdeFlags & (1 << 3)) != 0) {
+						final int numLocalVariablesInTypeTable = codeLocalVariableTypeTableN
+								.remove(codeLocalVariableTypeTableN.size() - 1);
+						for (int i = 0; i < numLocalVariablesInTypeTable; i++) {
+							final int location = codeLocalVariableTypeTableBciP.size() - 1;
+							codeLocalVariableTypeTableBciP.remove(location);
+							codeLocalVariableTypeTableSpanO.remove(location);
+							codeLocalVariableTypeTableNameRU.remove(location);
+							codeLocalVariableTypeTableTypeRS.remove(location);
+							codeLocalVariableTypeTableSlot.remove(location);
+						}
+					}
+					if ((cdeFlags & (1 << 1)) != 0) {
+						final int numLineNumbers = codeLineNumberTableN.remove(codeLineNumberTableN.size() - 1);
+						for (int i = 0; i < numLineNumbers; i++) {
+							final int location = codeLineNumberTableBciP.size() - 1;
+							codeLineNumberTableBciP.remove(location);
+							codeLineNumberTableLine.remove(location);
+						}
+					}
+				}
+			}
+			if ((flags & (1 << 21)) != 0) {
+				method_RVA_bands.removeLatest();
+			}
+			if ((flags & (1 << 22)) != 0) {
+				method_RIA_bands.removeLatest();
+			}
+			if ((flags & (1 << 23)) != 0) {
+				method_RVPA_bands.removeLatest();
+			}
+			if ((flags & (1 << 24)) != 0) {
+				method_RIPA_bands.removeLatest();
+			}
+			if ((flags & (1 << 25)) != 0) {
+				method_AD_bands.removeLatest();
+			}
+		}
+		class_this[index] = null;
+		class_super[index] = null;
+		class_interface_count[index] = 0;
+		class_interface[index] = null;
+		major_versions[index] = 0;
+		class_flags[index] = 0;
+		tempFieldDesc.clear();
+		tempFieldFlags.clear();
+		tempMethodDesc.clear();
+		tempMethodFlags.clear();
+		if (index > 0) {
+			index--;
+		}
+	}
+
+	public int numClassesProcessed() {
+		return index;
+	}
 }
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/CpBands.java b/src/main/java/org/apache/commons/compress/harmony/pack200/CpBands.java
index d75a7db3..7804b297 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/CpBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/CpBands.java
@@ -58,7 +58,7 @@ public class CpBands extends BandSet {
     private final Map<String, CPMethodOrField> stringsToCpField = new HashMap<>();
     private final Map<String, CPMethodOrField> stringsToCpIMethod = new HashMap<>();
 
-    private final Map<Object, CPConstant> objectsToCPConstant = new HashMap<>();
+    private final Map<Object, CPConstant<?>> objectsToCPConstant = new HashMap<>();
 
     private final Segment segment;
 
@@ -546,8 +546,8 @@ public class CpBands extends BandSet {
         return cpF;
     }
 
-    public CPConstant getConstant(final Object value) {
-        CPConstant constant = objectsToCPConstant.get(value);
+    public CPConstant<?> getConstant(final Object value) {
+        CPConstant<?> constant = objectsToCPConstant.get(value);
         if (constant == null) {
             if (value instanceof Integer) {
                 constant = new CPInt(((Integer) value).intValue());
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/FileBands.java b/src/main/java/org/apache/commons/compress/harmony/pack200/FileBands.java
index 28cd6a30..1ff665a5 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/FileBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/FileBands.java
@@ -60,8 +60,7 @@ public class FileBands extends BandSet {
         final int archiveModtime = segmentHeader.getArchive_modtime();
 
         final Set<String> classNames = new HashSet<>();
-        for (Object element : segmentUnit.getClassList()) {
-            final ClassReader reader = (ClassReader) element;
+        for (ClassReader reader : segmentUnit.getClassList()) {
             classNames.add(reader.getClassName());
         }
         final CPUTF8 emptyString = cpBands.getCPUtf8("");
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/IcBands.java b/src/main/java/org/apache/commons/compress/harmony/pack200/IcBands.java
index a29bd800..20f35266 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/IcBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/IcBands.java
@@ -124,9 +124,8 @@ public class IcBands extends BandSet {
             outerToInner.put(outerName, tuples);
             tuples.add(icTuple);
         } else {
-            for (Object tuple : tuples) {
-                final IcTuple icT = (IcTuple) tuple;
-                if (icTuple.equals(icT)) {
+            for (IcTuple tuple : tuples) {
+                if (icTuple.equals(tuple)) {
                     return;
                 }
             }
@@ -139,7 +138,7 @@ public class IcBands extends BandSet {
         return name.equals(outerName + '$' + innerName) && innerName.indexOf('$') == -1;
     }
 
-    class IcTuple implements Comparable {
+    class IcTuple implements Comparable<IcTuple> {
 
         protected CPClass C; // this class
         protected int F; // flags
@@ -169,8 +168,8 @@ public class IcBands extends BandSet {
         }
 
         @Override
-        public int compareTo(final Object arg0) {
-            return C.compareTo(((IcTuple) arg0).C);
+        public int compareTo(final IcTuple arg0) {
+            return C.compareTo(arg0.C);
         }
 
         public boolean isAnonymous() {
@@ -182,8 +181,7 @@ public class IcBands extends BandSet {
     }
 
     public IcTuple getIcTuple(final CPClass inner) {
-        for (Object element : innerClasses) {
-            final IcTuple icTuple = (IcTuple) element;
+        for (IcTuple icTuple : innerClasses) {
             if (icTuple.C.equals(inner)) {
                 return icTuple;
             }
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/MetadataBandGroup.java b/src/main/java/org/apache/commons/compress/harmony/pack200/MetadataBandGroup.java
index a28c3c59..38e7056d 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/MetadataBandGroup.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/MetadataBandGroup.java
@@ -36,22 +36,22 @@ public class MetadataBandGroup extends BandSet {
 
     public IntList param_NB = new IntList(); // TODO: Lazy instantiation?
     public IntList anno_N = new IntList();
-    public List type_RS = new ArrayList();
+    public List<CPSignature> type_RS = new ArrayList<>();
     public IntList pair_N = new IntList();
-    public List name_RU = new ArrayList();
-    public List T = new ArrayList();
-    public List caseI_KI = new ArrayList();
-    public List caseD_KD = new ArrayList();
-    public List caseF_KF = new ArrayList();
-    public List caseJ_KJ = new ArrayList();
-    public List casec_RS = new ArrayList();
-    public List caseet_RS = new ArrayList();
-    public List caseec_RU = new ArrayList();
-    public List cases_RU = new ArrayList();
+    public List<CPUTF8> name_RU = new ArrayList<>();
+    public List<String> T = new ArrayList<>();
+    public List<CPConstant<?>> caseI_KI = new ArrayList<>();
+    public List<CPConstant<?>> caseD_KD = new ArrayList<>();
+    public List<CPConstant<?>> caseF_KF = new ArrayList<>();
+    public List<CPConstant<?>> caseJ_KJ = new ArrayList<>();
+    public List<CPSignature> casec_RS = new ArrayList<>();
+    public List<CPSignature> caseet_RS = new ArrayList<>();
+    public List<CPUTF8> caseec_RU = new ArrayList<>();
+    public List<CPUTF8> cases_RU = new ArrayList<>();
     public IntList casearray_N = new IntList();
-    public List nesttype_RS = new ArrayList();
+    public List<CPSignature> nesttype_RS = new ArrayList<>();
     public IntList nestpair_N = new IntList();
-    public List nestname_RU = new ArrayList();
+    public List<CPUTF8> nestname_RU = new ArrayList<>();
 
     private final CpBands cpBands;
     private final int context;
@@ -199,10 +199,10 @@ public class MetadataBandGroup extends BandSet {
         }
     }
 
-    private int[] tagListToArray(final List t2) {
-        final int[] ints = new int[t2.size()];
+    private int[] tagListToArray(final List<String> list) {
+        final int[] ints = new int[list.size()];
         for (int i = 0; i < ints.length; i++) {
-            ints[i] = ((String) t2.get(i)).charAt(0);
+            ints[i] = list.get(i).charAt(0);
         }
         return ints;
     }
@@ -222,143 +222,140 @@ public class MetadataBandGroup extends BandSet {
      * @param nestNameRU TODO
      * @param nestPairN TODO
      */
-    public void addParameterAnnotation(final int numParams, final int[] annoN, final IntList pairN, final List typeRS,
-        final List nameRU, final List t, final List values, final List caseArrayN, final List nestTypeRS,
-        final List nestNameRU, final List nestPairN) {
-        param_NB.add(numParams);
-        for (int element : annoN) {
-            anno_N.add(element);
-        }
-        pair_N.addAll(pairN);
-        for (Object element : typeRS) {
-            final String desc = (String) element;
-            type_RS.add(cpBands.getCPSignature(desc));
-        }
-        for (Object element : nameRU) {
-            final String name = (String) element;
-            name_RU.add(cpBands.getCPUtf8(name));
-        }
-        final Iterator valuesIterator = values.iterator();
-        for (Object element : t) {
-            final String tag = (String) element;
-            T.add(tag);
-            if (tag.equals("B") || tag.equals("C") || tag.equals("I") || tag.equals("S") || tag.equals("Z")) {
-                final Integer value = (Integer) valuesIterator.next();
-                caseI_KI.add(cpBands.getConstant(value));
-            } else if (tag.equals("D")) {
-                final Double value = (Double) valuesIterator.next();
-                caseD_KD.add(cpBands.getConstant(value));
-            } else if (tag.equals("F")) {
-                final Float value = (Float) valuesIterator.next();
-                caseF_KF.add(cpBands.getConstant(value));
-            } else if (tag.equals("J")) {
-                final Long value = (Long) valuesIterator.next();
-                caseJ_KJ.add(cpBands.getConstant(value));
-            } else if (tag.equals("c")) {
-                final String value = (String) valuesIterator.next();
-                casec_RS.add(cpBands.getCPSignature(value));
-            } else if (tag.equals("e")) {
-                final String value = (String) valuesIterator.next();
-                final String value2 = (String) valuesIterator.next();
-                caseet_RS.add(cpBands.getCPSignature(value));
-                caseec_RU.add(cpBands.getCPUtf8(value2));
-            } else if (tag.equals("s")) {
-                final String value = (String) valuesIterator.next();
-                cases_RU.add(cpBands.getCPUtf8(value));
-            }
-            // do nothing here for [ or @ (handled below)
-        }
-        for (Object element : caseArrayN) {
-            final int arraySize = ((Integer) element).intValue();
-            casearray_N.add(arraySize);
-            numBackwardsCalls += arraySize;
-        }
-        for (Object element : nestTypeRS) {
-            final String type = (String) element;
-            nesttype_RS.add(cpBands.getCPSignature(type));
-        }
-        for (Object element : nestNameRU) {
-            final String name = (String) element;
-            nestname_RU.add(cpBands.getCPUtf8(name));
-        }
-        for (Object element : nestPairN) {
-            final Integer numPairs = (Integer) element;
-            nestpair_N.add(numPairs.intValue());
-            numBackwardsCalls += numPairs.intValue();
-        }
-    }
+	public void addParameterAnnotation(final int numParams, final int[] annoN, final IntList pairN,
+			final List<String> typeRS, final List<String> nameRU, final List<String> t, final List<Object> values,
+			final List<Integer> caseArrayN, final List<String> nestTypeRS, final List<String> nestNameRU,
+			final List<Integer> nestPairN) {
+		param_NB.add(numParams);
+		for (int element : annoN) {
+			anno_N.add(element);
+		}
+		pair_N.addAll(pairN);
+		for (String desc : typeRS) {
+			type_RS.add(cpBands.getCPSignature(desc));
+		}
+		for (String name : nameRU) {
+			name_RU.add(cpBands.getCPUtf8(name));
+		}
+		final Iterator<Object> valuesIterator = values.iterator();
+		for (String tag : t) {
+			T.add(tag);
+			if (tag.equals("B") || tag.equals("C") || tag.equals("I") || tag.equals("S") || tag.equals("Z")) {
+				final Integer value = (Integer) valuesIterator.next();
+				caseI_KI.add(cpBands.getConstant(value));
+			} else if (tag.equals("D")) {
+				final Double value = (Double) valuesIterator.next();
+				caseD_KD.add(cpBands.getConstant(value));
+			} else if (tag.equals("F")) {
+				final Float value = (Float) valuesIterator.next();
+				caseF_KF.add(cpBands.getConstant(value));
+			} else if (tag.equals("J")) {
+				final Long value = (Long) valuesIterator.next();
+				caseJ_KJ.add(cpBands.getConstant(value));
+			} else if (tag.equals("c")) {
+				final String value = (String) valuesIterator.next();
+				casec_RS.add(cpBands.getCPSignature(value));
+			} else if (tag.equals("e")) {
+				final String value = (String) valuesIterator.next();
+				final String value2 = (String) valuesIterator.next();
+				caseet_RS.add(cpBands.getCPSignature(value));
+				caseec_RU.add(cpBands.getCPUtf8(value2));
+			} else if (tag.equals("s")) {
+				final String value = (String) valuesIterator.next();
+				cases_RU.add(cpBands.getCPUtf8(value));
+			}
+			// do nothing here for [ or @ (handled below)
+		}
+		for (Object element : caseArrayN) {
+			final int arraySize = ((Integer) element).intValue();
+			casearray_N.add(arraySize);
+			numBackwardsCalls += arraySize;
+		}
+		for (Object element : nestTypeRS) {
+			final String type = (String) element;
+			nesttype_RS.add(cpBands.getCPSignature(type));
+		}
+		for (Object element : nestNameRU) {
+			final String name = (String) element;
+			nestname_RU.add(cpBands.getCPUtf8(name));
+		}
+		for (Object element : nestPairN) {
+			final Integer numPairs = (Integer) element;
+			nestpair_N.add(numPairs.intValue());
+			numBackwardsCalls += numPairs.intValue();
+		}
+	}
 
     /**
      * Add an annotation to this set of bands
      *
      * @param desc TODO
      * @param nameRU TODO
-     * @param t TODO
+     * @param tags TODO
      * @param values TODO
      * @param caseArrayN TODO
      * @param nestTypeRS TODO
      * @param nestNameRU TODO
      * @param nestPairN TODO
      */
-    public void addAnnotation(final String desc, final List nameRU, final List t, final List values,
-        final List caseArrayN, final List nestTypeRS, final List nestNameRU, final List nestPairN) {
-        type_RS.add(cpBands.getCPSignature(desc));
-        pair_N.add(nameRU.size());
-
-        for (Object element : nameRU) {
-            final String name = (String) element;
-            name_RU.add(cpBands.getCPUtf8(name));
-        }
-
-        final Iterator valuesIterator = values.iterator();
-        for (Object element : t) {
-            final String tag = (String) element;
-            T.add(tag);
-            if (tag.equals("B") || tag.equals("C") || tag.equals("I") || tag.equals("S") || tag.equals("Z")) {
-                final Integer value = (Integer) valuesIterator.next();
-                caseI_KI.add(cpBands.getConstant(value));
-            } else if (tag.equals("D")) {
-                final Double value = (Double) valuesIterator.next();
-                caseD_KD.add(cpBands.getConstant(value));
-            } else if (tag.equals("F")) {
-                final Float value = (Float) valuesIterator.next();
-                caseF_KF.add(cpBands.getConstant(value));
-            } else if (tag.equals("J")) {
-                final Long value = (Long) valuesIterator.next();
-                caseJ_KJ.add(cpBands.getConstant(value));
-            } else if (tag.equals("c")) {
-                final String value = (String) valuesIterator.next();
-                casec_RS.add(cpBands.getCPSignature(value));
-            } else if (tag.equals("e")) {
-                final String value = (String) valuesIterator.next();
-                final String value2 = (String) valuesIterator.next();
-                caseet_RS.add(cpBands.getCPSignature(value));
-                caseec_RU.add(cpBands.getCPUtf8(value2));
-            } else if (tag.equals("s")) {
-                final String value = (String) valuesIterator.next();
-                cases_RU.add(cpBands.getCPUtf8(value));
-            }
-            // do nothing here for [ or @ (handled below)
-        }
-        for (Object element : caseArrayN) {
-            final int arraySize = ((Integer) element).intValue();
-            casearray_N.add(arraySize);
-            numBackwardsCalls += arraySize;
-        }
-        for (Object element : nestTypeRS) {
-            final String type = (String) element;
-            nesttype_RS.add(cpBands.getCPSignature(type));
-        }
-        for (Object element : nestNameRU) {
-            final String name = (String) element;
-            nestname_RU.add(cpBands.getCPUtf8(name));
-        }
-        for (Object element : nestPairN) {
-            final Integer numPairs = (Integer) element;
-            nestpair_N.add(numPairs.intValue());
-            numBackwardsCalls += numPairs.intValue();
-        }
-    }
+	public void addAnnotation(final String desc, final List<String> nameRU, final List<String> tags,
+			final List<Object> values, final List<Integer> caseArrayN, final List<String> nestTypeRS,
+			final List<String> nestNameRU, final List<Integer> nestPairN) {
+		type_RS.add(cpBands.getCPSignature(desc));
+		pair_N.add(nameRU.size());
+
+		for (String name : nameRU) {
+			name_RU.add(cpBands.getCPUtf8(name));
+		}
+
+		final Iterator<Object> valuesIterator = values.iterator();
+		for (String tag : tags) {
+			T.add(tag);
+			if (tag.equals("B") || tag.equals("C") || tag.equals("I") || tag.equals("S") || tag.equals("Z")) {
+				final Integer value = (Integer) valuesIterator.next();
+				caseI_KI.add(cpBands.getConstant(value));
+			} else if (tag.equals("D")) {
+				final Double value = (Double) valuesIterator.next();
+				caseD_KD.add(cpBands.getConstant(value));
+			} else if (tag.equals("F")) {
+				final Float value = (Float) valuesIterator.next();
+				caseF_KF.add(cpBands.getConstant(value));
+			} else if (tag.equals("J")) {
+				final Long value = (Long) valuesIterator.next();
+				caseJ_KJ.add(cpBands.getConstant(value));
+			} else if (tag.equals("c")) {
+				final String value = (String) valuesIterator.next();
+				casec_RS.add(cpBands.getCPSignature(value));
+			} else if (tag.equals("e")) {
+				final String value = (String) valuesIterator.next();
+				final String value2 = (String) valuesIterator.next();
+				caseet_RS.add(cpBands.getCPSignature(value));
+				caseec_RU.add(cpBands.getCPUtf8(value2));
+			} else if (tag.equals("s")) {
+				final String value = (String) valuesIterator.next();
+				cases_RU.add(cpBands.getCPUtf8(value));
+			}
+			// do nothing here for [ or @ (handled below)
+		}
+		for (Object element : caseArrayN) {
+			final int arraySize = ((Integer) element).intValue();
+			casearray_N.add(arraySize);
+			numBackwardsCalls += arraySize;
+		}
+		for (Object element : nestTypeRS) {
+			final String type = (String) element;
+			nesttype_RS.add(cpBands.getCPSignature(type));
+		}
+		for (Object element : nestNameRU) {
+			final String name = (String) element;
+			nestname_RU.add(cpBands.getCPUtf8(name));
+		}
+		for (Object element : nestPairN) {
+			final Integer numPairs = (Integer) element;
+			nestpair_N.add(numPairs.intValue());
+			numBackwardsCalls += numPairs.intValue();
+		}
+	}
 
     /**
      * Returns true if any annotations have been added to this set of bands.
@@ -399,7 +396,7 @@ public class MetadataBandGroup extends BandSet {
      * Convenience method for removeLatest
      */
     private void removeOnePair() {
-        final String tag = (String) T.remove(T.size() - 1);
+        final String tag = T.remove(T.size() - 1);
         if (tag.equals("B") || tag.equals("C") || tag.equals("I") || tag.equals("S") || tag.equals("Z")) {
             caseI_KI.remove(caseI_KI.size() - 1);
         } else if (tag.equals("D")) {
diff --git a/src/main/java/org/apache/commons/compress/harmony/pack200/Segment.java b/src/main/java/org/apache/commons/compress/harmony/pack200/Segment.java
index 7e9e2ba0..6a7d4b75 100644
--- a/src/main/java/org/apache/commons/compress/harmony/pack200/Segment.java
+++ b/src/main/java/org/apache/commons/compress/harmony/pack200/Segment.java
@@ -415,7 +415,7 @@ public class Segment extends ClassVisitor {
         }
 
         @Override
-        public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label[] labels) {
+        public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) {
             bcBands.visitTableSwitchInsn(min, max, dflt, labels);
         }
 
@@ -445,13 +445,13 @@ public class Segment extends ClassVisitor {
         private String desc;
         private boolean visible;
 
-        private final List nameRU = new ArrayList();
-        private final List T = new ArrayList(); // tags
-        private final List values = new ArrayList();
-        private final List caseArrayN = new ArrayList();
-        private final List nestTypeRS = new ArrayList();
-        private final List nestNameRU = new ArrayList();
-        private final List nestPairN = new ArrayList();
+        private final List<String> nameRU = new ArrayList<>();
+        private final List<String> tags = new ArrayList<>(); // tags
+        private final List<Object> values = new ArrayList<>();
+        private final List<Integer> caseArrayN = new ArrayList<>();
+        private final List<String> nestTypeRS = new ArrayList<>();
+        private final List<String> nestNameRU = new ArrayList<>();
+        private final List<Integer> nestPairN = new ArrayList<>();
 
         public SegmentAnnotationVisitor(final int context, final String desc, final boolean visible) {
             super(ASM_API);
@@ -480,12 +480,12 @@ public class Segment extends ClassVisitor {
                 name = "";
             }
             nameRU.add(name);
-            addValueAndTag(value, T, values);
+            addValueAndTag(value, tags, values);
         }
 
         @Override
         public AnnotationVisitor visitAnnotation(String name, final String desc) {
-            T.add("@");
+            tags.add("@");
             if (name == null) {
                 name = "";
             }
@@ -495,10 +495,10 @@ public class Segment extends ClassVisitor {
             return new AnnotationVisitor(context, av) {
                 @Override
                 public void visit(final String name, final Object value) {
-                    final Integer numPairs = (Integer) nestPairN.remove(nestPairN.size() - 1);
+                    final Integer numPairs = nestPairN.remove(nestPairN.size() - 1);
                     nestPairN.add(Integer.valueOf(numPairs.intValue() + 1));
                     nestNameRU.add(name);
-                    addValueAndTag(value, T, values);
+                    addValueAndTag(value, tags, values);
                 }
 
                 @Override
@@ -519,9 +519,9 @@ public class Segment extends ClassVisitor {
 
                 @Override
                 public void visitEnum(final String name, final String desc, final String value) {
-                    final Integer numPairs = (Integer) nestPairN.remove(nestPairN.size() - 1);
+                    final Integer numPairs = nestPairN.remove(nestPairN.size() - 1);
                     nestPairN.add(Integer.valueOf(numPairs.intValue() + 1));
-                    T.add("e");
+                    tags.add("e");
                     nestNameRU.add(name);
                     values.add(desc);
                     values.add(value);
@@ -531,32 +531,32 @@ public class Segment extends ClassVisitor {
 
         @Override
         public AnnotationVisitor visitArray(String name) {
-            T.add("[");
+            tags.add("[");
             if (name == null) {
                 name = "";
             }
             nameRU.add(name);
             caseArrayN.add(Integer.valueOf(0));
-            return new ArrayVisitor(caseArrayN, T, nameRU, values);
+            return new ArrayVisitor(caseArrayN, tags, nameRU, values);
         }
 
         @Override
         public void visitEnd() {
             if (desc == null) {
-                Segment.this.classBands.addAnnotationDefault(nameRU, T, values, caseArrayN, nestTypeRS, nestNameRU,
+                Segment.this.classBands.addAnnotationDefault(nameRU, tags, values, caseArrayN, nestTypeRS, nestNameRU,
                     nestPairN);
             } else if (parameter != -1) {
-                Segment.this.classBands.addParameterAnnotation(parameter, desc, visible, nameRU, T, values, caseArrayN,
+                Segment.this.classBands.addParameterAnnotation(parameter, desc, visible, nameRU, tags, values, caseArrayN,
                     nestTypeRS, nestNameRU, nestPairN);
             } else {
-                Segment.this.classBands.addAnnotation(context, desc, visible, nameRU, T, values, caseArrayN, nestTypeRS,
+                Segment.this.classBands.addAnnotation(context, desc, visible, nameRU, tags, values, caseArrayN, nestTypeRS,
                     nestNameRU, nestPairN);
             }
         }
 
         @Override
         public void visitEnum(String name, final String desc, final String value) {
-            T.add("e");
+            tags.add("e");
             if (name == null) {
                 name = "";
             }
@@ -569,16 +569,16 @@ public class Segment extends ClassVisitor {
     public class ArrayVisitor extends AnnotationVisitor {
 
         private final int indexInCaseArrayN;
-        private final List caseArrayN;
-        private final List values;
-        private final List nameRU;
-        private final List T;
+        private final List<Integer> caseArrayN;
+        private final List<Object> values;
+        private final List<String> nameRU;
+        private final List<String> tags;
 
-        public ArrayVisitor(final List caseArrayN, final List T, final List nameRU, final List values) {
+        public ArrayVisitor(final List<Integer> caseArrayN, final List<String> tags, final List<String> nameRU, final List<Object> values) {
             super(ASM_API);
 
             this.caseArrayN = caseArrayN;
-            this.T = T;
+            this.tags = tags;
             this.nameRU = nameRU;
             this.values = values;
             this.indexInCaseArrayN = caseArrayN.size() - 1;
@@ -586,12 +586,12 @@ public class Segment extends ClassVisitor {
 
         @Override
         public void visit(String name, final Object value) {
-            final Integer numCases = (Integer) caseArrayN.remove(indexInCaseArrayN);
+            final Integer numCases = caseArrayN.remove(indexInCaseArrayN);
             caseArrayN.add(indexInCaseArrayN, Integer.valueOf(numCases.intValue() + 1));
             if (name == null) {
                 name = "";
             }
-            addValueAndTag(value, T, values);
+            addValueAndTag(value, tags, values);
         }
 
         @Override
@@ -601,13 +601,13 @@ public class Segment extends ClassVisitor {
 
         @Override
         public AnnotationVisitor visitArray(String name) {
-            T.add("[");
+            tags.add("[");
             if (name == null) {
                 name = "";
             }
             nameRU.add(name);
             caseArrayN.add(Integer.valueOf(0));
-            return new ArrayVisitor(caseArrayN, T, nameRU, values);
+            return new ArrayVisitor(caseArrayN, tags, nameRU, values);
         }
 
         @Override
@@ -616,9 +616,9 @@ public class Segment extends ClassVisitor {
 
         @Override
         public void visitEnum(final String name, final String desc, final String value) {
-            final Integer numCases = (Integer) caseArrayN.remove(caseArrayN.size() - 1);
+            final Integer numCases = caseArrayN.remove(caseArrayN.size() - 1);
             caseArrayN.add(Integer.valueOf(numCases.intValue() + 1));
-            T.add("e");
+            tags.add("e");
             values.add(desc);
             values.add(value);
         }
@@ -670,36 +670,36 @@ public class Segment extends ClassVisitor {
     }
 
     // helper method for annotation visitors
-    private void addValueAndTag(final Object value, final List T, final List values) {
+    private void addValueAndTag(final Object value, final List<String> tags, final List<Object> values) {
         if (value instanceof Integer) {
-            T.add("I");
+            tags.add("I");
             values.add(value);
         } else if (value instanceof Double) {
-            T.add("D");
+            tags.add("D");
             values.add(value);
         } else if (value instanceof Float) {
-            T.add("F");
+            tags.add("F");
             values.add(value);
         } else if (value instanceof Long) {
-            T.add("J");
+            tags.add("J");
             values.add(value);
         } else if (value instanceof Byte) {
-            T.add("B");
+            tags.add("B");
             values.add(Integer.valueOf(((Byte) value).intValue()));
         } else if (value instanceof Character) {
-            T.add("C");
+            tags.add("C");
             values.add(Integer.valueOf(((Character) value).charValue()));
         } else if (value instanceof Short) {
-            T.add("S");
+            tags.add("S");
             values.add(Integer.valueOf(((Short) value).intValue()));
         } else if (value instanceof Boolean) {
-            T.add("Z");
+            tags.add("Z");
             values.add(Integer.valueOf(((Boolean) value).booleanValue() ? 1 : 0));
         } else if (value instanceof String) {
-            T.add("s");
+            tags.add("s");
             values.add(value);
         } else if (value instanceof Type) {
-            T.add("c");
+            tags.add("c");
             values.add(((Type) value).toString());
         }
     }
@@ -738,5 +738,7 @@ public class Segment extends ClassVisitor {
      */
     public static class PassException extends RuntimeException {
 
+		private static final long serialVersionUID = 1L;
+
     }
 }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/AttributeLayoutMap.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/AttributeLayoutMap.java
index aca5725e..a8579ab0 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/AttributeLayoutMap.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/AttributeLayoutMap.java
@@ -120,17 +120,17 @@ public class AttributeLayoutMap {
             new AttributeLayout(AttributeLayout.ATTRIBUTE_ANNOTATION_DEFAULT, AttributeLayout.CONTEXT_METHOD, "*", 25)};
     }
 
-    private final Map classLayouts = new HashMap();
-    private final Map fieldLayouts = new HashMap();
-    private final Map methodLayouts = new HashMap();
-    private final Map codeLayouts = new HashMap();
+    private final Map<Integer, AttributeLayout> classLayouts = new HashMap<>();
+    private final Map<Integer, AttributeLayout> fieldLayouts = new HashMap<>();
+    private final Map<Integer, AttributeLayout> methodLayouts = new HashMap<>();
+    private final Map<Integer, AttributeLayout> codeLayouts = new HashMap<>();
 
     // The order of the maps in this array should not be changed as their
     // indices correspond to
     // the value of their context constants (AttributeLayout.CONTEXT_CLASS etc.)
-    private final Map[] layouts = {classLayouts, fieldLayouts, methodLayouts, codeLayouts};
+	private final Map[] layouts = { classLayouts, fieldLayouts, methodLayouts, codeLayouts };
 
-    private final Map layoutsToBands = new HashMap();
+    private final Map<AttributeLayout, NewAttributeBands> layoutsToBands = new HashMap<>();
 
     public AttributeLayoutMap() throws Pack200Exception {
         final AttributeLayout[] defaultAttributeLayouts = getDefaultAttributeLayouts();
@@ -140,7 +140,7 @@ public class AttributeLayoutMap {
     }
 
     public void add(final AttributeLayout layout) {
-        layouts[layout.getContext()].put(Integer.valueOf(layout.getIndex()), layout);
+        getLayout(layout.getContext()).put(Integer.valueOf(layout.getIndex()), layout);
     }
 
     public void add(final AttributeLayout layout, final NewAttributeBands newBands) {
@@ -148,38 +148,22 @@ public class AttributeLayoutMap {
         layoutsToBands.put(layout, newBands);
     }
 
-    public AttributeLayout getAttributeLayout(final String name, final int context) {
-        final Map map = layouts[context];
-        for (Object element : map.values()) {
-            final AttributeLayout layout = (AttributeLayout) element;
-            if (layout.getName().equals(name)) {
-                return layout;
-            }
-        }
-        return null;
-    }
-
-    public AttributeLayout getAttributeLayout(final int index, final int context) {
-        final Map map = layouts[context];
-        return (AttributeLayout) map.get(Integer.valueOf(index));
-    }
-
     /**
      * The map should not contain the same layout and name combination more than once for each context.
      *
      * @throws Pack200Exception Thrown when the name layout/name combination exists twice for a context.
      */
     public void checkMap() throws Pack200Exception {
-        for (final Map map : layouts) {
-            Collection c = map.values();
+        for (final Map<Integer, AttributeLayout> map : layouts) {
+            Collection<AttributeLayout> c = map.values();
             if (!(c instanceof List)) {
-                c = new ArrayList(c);
+                c = new ArrayList<>(c);
             }
-            final List l = (List) c;
-            for (int j = 0; j < l.size(); j++) {
-                final AttributeLayout layout1 = (AttributeLayout) l.get(j);
-                for (int j2 = j + 1; j2 < l.size(); j2++) {
-                    final AttributeLayout layout2 = (AttributeLayout) l.get(j2);
+            final List<AttributeLayout> layouts = (List<AttributeLayout>) c;
+            for (int j = 0; j < layouts.size(); j++) {
+                final AttributeLayout layout1 = layouts.get(j);
+                for (int j2 = j + 1; j2 < layouts.size(); j2++) {
+                    final AttributeLayout layout2 = layouts.get(j2);
                     if (layout1.getName().equals(layout2.getName())
                         && layout1.getLayout().equals(layout2.getLayout())) {
                         throw new Pack200Exception(
@@ -191,8 +175,27 @@ public class AttributeLayoutMap {
         }
     }
 
-    public NewAttributeBands getAttributeBands(final AttributeLayout layout) {
-        return (NewAttributeBands) layoutsToBands.get(layout);
+	public NewAttributeBands getAttributeBands(final AttributeLayout layout) {
+        return layoutsToBands.get(layout);
     }
 
+    public AttributeLayout getAttributeLayout(final int index, final int context) {
+        final Map<Integer, AttributeLayout> map = getLayout(context);
+        return map.get(Integer.valueOf(index));
+    }
+
+    public AttributeLayout getAttributeLayout(final String name, final int context) {
+        final Map<Integer, AttributeLayout> map = getLayout(context);
+        for (AttributeLayout layout : map.values()) {
+            if (layout.getName().equals(name)) {
+                return layout;
+            }
+        }
+        return null;
+    }
+
+    private Map<Integer, AttributeLayout> getLayout(final int context) {
+		return layouts[context];
+	}
+
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/BcBands.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/BcBands.java
index fbab0721..1a962562 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/BcBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/BcBands.java
@@ -70,7 +70,7 @@ public class BcBands extends BandSet {
     private int[] bcEscSize;
     private int[][] bcEscByte;
 
-    private List wideByteCodes;
+    private List<Integer> wideByteCodes;
 
     /**
      * @param segment TODO
@@ -121,8 +121,8 @@ public class BcBands extends BandSet {
         methodByteCodePacked = new byte[classCount][][];
         int bcParsed = 0;
 
-        final List switchIsTableSwitch = new ArrayList();
-        wideByteCodes = new ArrayList();
+        final List<Boolean> switchIsTableSwitch = new ArrayList<>();
+        wideByteCodes = new ArrayList<>();
         for (int c = 0; c < classCount; c++) {
             final int numberOfMethods = methodFlags[c].length;
             methodByteCodePacked[c] = new byte[numberOfMethods][];
@@ -293,7 +293,7 @@ public class BcBands extends BandSet {
         bcCaseCount = decodeBandInt("bc_case_count", in, Codec.UNSIGNED5, bcCaseCountCount);
         int bcCaseValueCount = 0;
         for (int i = 0; i < bcCaseCount.length; i++) {
-            final boolean isTableSwitch = ((Boolean) switchIsTableSwitch.get(i)).booleanValue();
+            final boolean isTableSwitch = switchIsTableSwitch.get(i).booleanValue();
             if (isTableSwitch) {
                 bcCaseValueCount += 1;
             } else {
@@ -337,7 +337,7 @@ public class BcBands extends BandSet {
         final long[][] methodFlags = segment.getClassBands().getMethodFlags();
         final int[] codeMaxNALocals = segment.getClassBands().getCodeMaxNALocals();
         final int[] codeMaxStack = segment.getClassBands().getCodeMaxStack();
-        final ArrayList[][] methodAttributes = segment.getClassBands().getMethodAttributes();
+        final ArrayList<Attribute>[][] methodAttributes = segment.getClassBands().getMethodAttributes();
         final String[][] methodDescr = segment.getClassBands().getMethodDescr();
 
         final AttributeLayoutMap attributeDefinitionMap = segment.getAttrDefinitionBands().getAttributeDefinitionMap();
@@ -351,7 +351,7 @@ public class BcBands extends BandSet {
 
         final int[] wideByteCodeArray = new int[wideByteCodes.size()];
         for (int index = 0; index < wideByteCodeArray.length; index++) {
-            wideByteCodeArray[index] = ((Integer) wideByteCodes.get(index)).intValue();
+            wideByteCodeArray[index] = wideByteCodes.get(index).intValue();
         }
         final OperandManager operandManager = new OperandManager(bcCaseCount, bcCaseValue, bcByte, bcShort, bcLocal,
             bcLabel, bcIntRef, bcFloatRef, bcLongRef, bcDoubleRef, bcStringRef, bcClassRef, bcFieldRef, bcMethodRef,
@@ -359,7 +359,7 @@ public class BcBands extends BandSet {
         operandManager.setSegment(segment);
 
         int i = 0;
-        final ArrayList orderedCodeAttributes = segment.getClassBands().getOrderedCodeAttributes();
+        final ArrayList<List<Attribute>> orderedCodeAttributes = segment.getClassBands().getOrderedCodeAttributes();
         int codeAttributeIndex = 0;
 
         // Exception table fields
@@ -387,7 +387,7 @@ public class BcBands extends BandSet {
                     final String[] cpClass = segment.getCpBands().getCpClass();
                     operandManager.setCurrentClass(cpClass[segment.getClassBands().getClassThisInts()[c]]);
                     operandManager.setSuperClass(cpClass[segment.getClassBands().getClassSuperInts()[c]]);
-                    final List exceptionTable = new ArrayList();
+                    final List<ExceptionTableEntry> exceptionTable = new ArrayList<>();
                     if (handlerCount != null) {
                         for (int j = 0; j < handlerCount[i]; j++) {
                             final int handlerClass = handlerClassTypes[i][j] - 1;
@@ -405,11 +405,10 @@ public class BcBands extends BandSet {
                     }
                     final CodeAttribute codeAttr = new CodeAttribute(maxStack, maxLocal, methodByteCodePacked[c][m],
                         segment, operandManager, exceptionTable);
-                    final ArrayList methodAttributesList = methodAttributes[c][m];
+                    final List<Attribute> methodAttributesList = methodAttributes[c][m];
                     // Make sure we add the code attribute in the right place
                     int indexForCodeAttr = 0;
-                    for (Object element : methodAttributesList) {
-                        final Attribute attribute = (Attribute) element;
+                    for (Attribute attribute : methodAttributesList) {
                         if (!(attribute instanceof NewAttribute)
                             || (((NewAttribute) attribute).getLayoutIndex() >= 15)) {
                             break;
@@ -418,11 +417,11 @@ public class BcBands extends BandSet {
                     }
                     methodAttributesList.add(indexForCodeAttr, codeAttr);
                     codeAttr.renumber(codeAttr.byteCodeOffsets);
-                    List currentAttributes;
+                    List<Attribute> currentAttributes;
                     if (allCodeHasFlags) {
-                        currentAttributes = (List) orderedCodeAttributes.get(i);
+                        currentAttributes = orderedCodeAttributes.get(i);
                     } else if (codeHasFlags[i]) {
-                        currentAttributes = (List) orderedCodeAttributes.get(codeAttributeIndex);
+                        currentAttributes = orderedCodeAttributes.get(codeAttributeIndex);
                         codeAttributeIndex++;
                     } else {
                         currentAttributes = Collections.EMPTY_LIST;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/ClassBands.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/ClassBands.java
index 13bb1af7..c38c077c 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/ClassBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/ClassBands.java
@@ -60,7 +60,7 @@ public class ClassBands extends BandSet {
 
     private int[] classThisInts;
 
-    private ArrayList[] classAttributes;
+    private ArrayList<Attribute>[] classAttributes;
 
     private int[] classVersionMajor;
 
@@ -68,7 +68,7 @@ public class ClassBands extends BandSet {
 
     private IcTuple[][] icLocal;
 
-    private List[] codeAttributes;
+    private List<Attribute>[] codeAttributes;
 
     private int[] codeHandlerCount;
 
@@ -76,7 +76,7 @@ public class ClassBands extends BandSet {
 
     private int[] codeMaxStack;
 
-    private ArrayList[][] fieldAttributes;
+    private ArrayList<Attribute>[][] fieldAttributes;
 
     private String[][] fieldDescr;
 
@@ -86,7 +86,7 @@ public class ClassBands extends BandSet {
 
     private long[][] fieldAccessFlags;
 
-    private ArrayList[][] methodAttributes;
+    private ArrayList<Attribute>[][] methodAttributes;
 
     private String[][] methodDescr;
 
@@ -174,7 +174,7 @@ public class ClassBands extends BandSet {
         for (int i = 0; i < classCount; i++) {
             fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
             for (int j = 0; j < fieldFlags[i].length; j++) {
-                fieldAttributes[i][j] = new ArrayList();
+                fieldAttributes[i][j] = new ArrayList<>();
             }
         }
 
@@ -231,7 +231,7 @@ public class ClassBands extends BandSet {
         final int limit = options.hasFieldFlagsHi() ? 62 : 31;
         final AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
         final int[] counts = new int[limit + 1];
-        final List[] otherAttributes = new List[limit + 1];
+        final List<Attribute>[] otherAttributes = new List[limit + 1];
         for (int i = 0; i < limit; i++) {
             final AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_FIELD);
             if (layout != null && !(layout.isDefaultLayout())) {
@@ -292,7 +292,7 @@ public class ClassBands extends BandSet {
         for (int i = 0; i < classCount; i++) {
             methodAttributes[i] = new ArrayList[methodFlags[i].length];
             for (int j = 0; j < methodFlags[i].length; j++) {
-                methodAttributes[i][j] = new ArrayList();
+                methodAttributes[i][j] = new ArrayList<>();
             }
         }
 
@@ -355,7 +355,6 @@ public class ClassBands extends BandSet {
         final int limit = options.hasMethodFlagsHi() ? 62 : 31;
         final AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
         final int[] counts = new int[limit + 1];
-        final List[] otherAttributes = new List[limit + 1];
         for (int i = 0; i < limit; i++) {
             final AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_METHOD);
             if (layout != null && !(layout.isDefaultLayout())) {
@@ -363,6 +362,7 @@ public class ClassBands extends BandSet {
                 counts[i] = SegmentUtils.countMatches(methodFlags, layout);
             }
         }
+        final List<Attribute>[] otherAttributes = new List[limit + 1];
         for (int i = 0; i < counts.length; i++) {
             if (counts[i] > 0) {
                 final NewAttributeBands bands = attrMap.getAttributeBands(otherLayouts[i]);
@@ -428,7 +428,7 @@ public class ClassBands extends BandSet {
         // Prepare empty attribute lists
         classAttributes = new ArrayList[classCount];
         for (int i = 0; i < classCount; i++) {
-            classAttributes[i] = new ArrayList();
+            classAttributes[i] = new ArrayList<>();
         }
 
         classFlags = parseFlags("class_flags", in, classCount, Codec.UNSIGNED5, options.hasClassFlagsHi());
@@ -501,7 +501,7 @@ public class ClassBands extends BandSet {
         final int limit = options.hasClassFlagsHi() ? 62 : 31;
         final AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
         final int[] counts = new int[limit + 1];
-        final List[] otherAttributes = new List[limit + 1];
+        final List<Attribute>[] otherAttributes = new List[limit + 1];
         for (int i = 0; i < limit; i++) {
             final AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_CLASS);
             if (layout != null && !(layout.isDefaultLayout())) {
@@ -702,7 +702,7 @@ public class ClassBands extends BandSet {
 
         codeAttributes = new List[codeFlagsCount];
         for (int i = 0; i < codeAttributes.length; i++) {
-            codeAttributes[i] = new ArrayList();
+            codeAttributes[i] = new ArrayList<>();
         }
         parseCodeAttrBands(in, codeFlagsCount);
     }
@@ -773,7 +773,7 @@ public class ClassBands extends BandSet {
         final int limit = options.hasCodeFlagsHi() ? 62 : 31;
         final AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
         final int[] counts = new int[limit + 1];
-        final List[] otherAttributes = new List[limit + 1];
+        final List<Attribute>[] otherAttributes = new List[limit + 1];
         for (int i = 0; i < limit; i++) {
             final AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_CODE);
             if (layout != null && !(layout.isDefaultLayout())) {
@@ -859,8 +859,8 @@ public class ClassBands extends BandSet {
             backwardsCallsUsed++;
         }
         final MetadataBandGroup[] mb = parseMetadata(in, RxA, RxACount, backwardsCalls, "field");
-        final List rvaAttributes = mb[0].getAttributes();
-        final List riaAttributes = mb[1].getAttributes();
+        final List<Attribute> rvaAttributes = mb[0].getAttributes();
+        final List<Attribute> riaAttributes = mb[1].getAttributes();
         int rvaAttributesIndex = 0;
         int riaAttributesIndex = 0;
         for (int i = 0; i < fieldFlags.length; i++) {
@@ -1003,7 +1003,7 @@ public class ClassBands extends BandSet {
             }
         }
         final MetadataBandGroup[] mbgs = parseMetadata(in, RxA, rxaCounts, backwardsCalls, "method");
-        final List[] attributeLists = new List[RxA.length];
+        final List<Attribute>[] attributeLists = new List[RxA.length];
         final int[] attributeListIndexes = new int[RxA.length];
         for (int i = 0; i < mbgs.length; i++) {
             attributeLists[i] = mbgs[i].getAttributes();
@@ -1055,8 +1055,8 @@ public class ClassBands extends BandSet {
             backwardsCalls[1] = classAttrCalls[0];
         }
         final MetadataBandGroup[] mbgs = parseMetadata(in, RxA, RxACount, backwardsCalls, "class");
-        final List rvaAttributes = mbgs[0].getAttributes();
-        final List riaAttributes = mbgs[1].getAttributes();
+        final List<Attribute> rvaAttributes = mbgs[0].getAttributes();
+        final List<Attribute> riaAttributes = mbgs[1].getAttributes();
         int rvaAttributesIndex = 0;
         int riaAttributesIndex = 0;
         for (int i = 0; i < classFlags.length; i++) {
@@ -1070,7 +1070,7 @@ public class ClassBands extends BandSet {
         return numBackwardsCalls;
     }
 
-    public ArrayList[] getClassAttributes() {
+    public ArrayList<Attribute>[] getClassAttributes() {
         return classAttributes;
     }
 
@@ -1123,7 +1123,7 @@ public class ClassBands extends BandSet {
         return codeMaxStack;
     }
 
-    public ArrayList[][] getFieldAttributes() {
+    public ArrayList<Attribute>[][] getFieldAttributes() {
         return fieldAttributes;
     }
 
@@ -1162,20 +1162,19 @@ public class ClassBands extends BandSet {
      *
      * @return ArrayList
      */
-    public ArrayList getOrderedCodeAttributes() {
-        final ArrayList orderedAttributeList = new ArrayList(codeAttributes.length);
+    public ArrayList<List<Attribute>> getOrderedCodeAttributes() {
+        final ArrayList<List<Attribute>> orderedAttributeList = new ArrayList<>(codeAttributes.length);
         for (int classIndex = 0; classIndex < codeAttributes.length; classIndex++) {
-            final ArrayList currentAttributes = new ArrayList(codeAttributes[classIndex].size());
+            final List<Attribute> currentAttributes = new ArrayList<>(codeAttributes[classIndex].size());
             for (int attributeIndex = 0; attributeIndex < codeAttributes[classIndex].size(); attributeIndex++) {
-                final Attribute attribute = (Attribute) codeAttributes[classIndex].get(attributeIndex);
-                currentAttributes.add(attribute);
+                currentAttributes.add(codeAttributes[classIndex].get(attributeIndex));
             }
             orderedAttributeList.add(currentAttributes);
         }
         return orderedAttributeList;
     }
 
-    public ArrayList[][] getMethodAttributes() {
+    public ArrayList<Attribute>[][] getMethodAttributes() {
         return methodAttributes;
     }
 
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/CpBands.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/CpBands.java
index cd5f2746..e9220197 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/CpBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/CpBands.java
@@ -74,17 +74,17 @@ public class CpBands extends BandSet {
     private int[] cpStringInts;
     private String[] cpUTF8;
 
-    private final Map stringsToCPUTF8 = new HashMap();
-    private final Map stringsToCPStrings = new HashMap();
-    private final Map longsToCPLongs = new HashMap();
-    private final Map integersToCPIntegers = new HashMap();
-    private final Map floatsToCPFloats = new HashMap();
-    private final Map stringsToCPClass = new HashMap();
-    private final Map doublesToCPDoubles = new HashMap();
-    private final Map descriptorsToCPNameAndTypes = new HashMap();
-
-    private Map mapClass;
-    private Map mapDescriptor;
+    private final Map<String, CPUTF8> stringsToCPUTF8 = new HashMap<>();
+    private final Map<String, CPString> stringsToCPStrings = new HashMap<>();
+    private final Map<Long, CPLong> longsToCPLongs = new HashMap<>();
+    private final Map<Integer, CPInteger> integersToCPIntegers = new HashMap<>();
+    private final Map<Float, CPFloat> floatsToCPFloats = new HashMap<>();
+    private final Map<String, CPClass> stringsToCPClass = new HashMap<>();
+    private final Map<Double, CPDouble> doublesToCPDoubles = new HashMap<>();
+    private final Map<String, CPNameAndType> descriptorsToCPNameAndTypes = new HashMap<>();
+
+    private Map<String, Integer> mapClass;
+    private Map<String, Integer> mapDescriptor;
     private Map<String, Integer> mapUTF8;
 
     // TODO: Not used
@@ -151,7 +151,7 @@ public class CpBands extends BandSet {
         final int cpClassCount = header.getCpClassCount();
         cpClassInts = decodeBandInt("cp_Class", in, Codec.UDELTA5, cpClassCount);
         cpClass = new String[cpClassCount];
-        mapClass = new HashMap(cpClassCount);
+        mapClass = new HashMap<>(cpClassCount);
         for (int i = 0; i < cpClassCount; i++) {
             cpClass[i] = cpUTF8[cpClassInts[i]];
             mapClass.put(cpClass[i], Integer.valueOf(i));
@@ -175,7 +175,7 @@ public class CpBands extends BandSet {
         final String[] cpDescriptorNames = getReferences(cpDescriptorNameInts, cpUTF8);
         final String[] cpDescriptorTypes = getReferences(cpDescriptorTypeInts, cpSignature);
         cpDescriptor = new String[cpDescriptorCount];
-        mapDescriptor = new HashMap(cpDescriptorCount);
+        mapDescriptor = new HashMap<>(cpDescriptorCount);
         for (int i = 0; i < cpDescriptorCount; i++) {
             cpDescriptor[i] = cpDescriptorNames[i] + ":" + cpDescriptorTypes[i]; //$NON-NLS-1$
             mapDescriptor.put(cpDescriptor[i], Integer.valueOf(i));
@@ -306,7 +306,7 @@ public class CpBands extends BandSet {
             final String form = cpSignatureForm[i];
             final int len = form.length();
             final StringBuilder signature = new StringBuilder(64);
-            final ArrayList list = new ArrayList();
+            final ArrayList<String> list = new ArrayList<>();
             for (int j = 0; j < len; j++) {
                 final char c = form.charAt(j);
                 signature.append(c);
@@ -445,7 +445,7 @@ public class CpBands extends BandSet {
 
     public CPUTF8 cpUTF8Value(final int index) {
         final String string = cpUTF8[index];
-        CPUTF8 cputf8 = (CPUTF8) stringsToCPUTF8.get(string);
+        CPUTF8 cputf8 = stringsToCPUTF8.get(string);
         if (cputf8 == null) {
             cputf8 = new CPUTF8(string, index);
             stringsToCPUTF8.put(string, cputf8);
@@ -460,7 +460,7 @@ public class CpBands extends BandSet {
     }
 
     public CPUTF8 cpUTF8Value(final String string, final boolean searchForIndex) {
-        CPUTF8 cputf8 = (CPUTF8) stringsToCPUTF8.get(string);
+        CPUTF8 cputf8 = stringsToCPUTF8.get(string);
         if (cputf8 == null) {
             Integer index = null;
             if (searchForIndex) {
@@ -485,7 +485,7 @@ public class CpBands extends BandSet {
         final String string = cpString[index];
         final int utf8Index = cpStringInts[index];
         final int globalIndex = stringOffset + index;
-        CPString cpString = (CPString) stringsToCPStrings.get(string);
+        CPString cpString = stringsToCPStrings.get(string);
         if (cpString == null) {
             cpString = new CPString(cpUTF8Value(utf8Index), globalIndex);
             stringsToCPStrings.put(string, cpString);
@@ -495,7 +495,7 @@ public class CpBands extends BandSet {
 
     public CPLong cpLongValue(final int index) {
         final Long l = Long.valueOf(cpLong[index]);
-        CPLong cpLong = (CPLong) longsToCPLongs.get(l);
+        CPLong cpLong = longsToCPLongs.get(l);
         if (cpLong == null) {
             cpLong = new CPLong(l, index + longOffset);
             longsToCPLongs.put(l, cpLong);
@@ -505,7 +505,7 @@ public class CpBands extends BandSet {
 
     public CPInteger cpIntegerValue(final int index) {
         final Integer i = Integer.valueOf(cpInt[index]);
-        CPInteger cpInteger = (CPInteger) integersToCPIntegers.get(i);
+        CPInteger cpInteger = integersToCPIntegers.get(i);
         if (cpInteger == null) {
             cpInteger = new CPInteger(i, index + intOffset);
             integersToCPIntegers.put(i, cpInteger);
@@ -515,7 +515,7 @@ public class CpBands extends BandSet {
 
     public CPFloat cpFloatValue(final int index) {
         final Float f = Float.valueOf(cpFloat[index]);
-        CPFloat cpFloat = (CPFloat) floatsToCPFloats.get(f);
+        CPFloat cpFloat = floatsToCPFloats.get(f);
         if (cpFloat == null) {
             cpFloat = new CPFloat(f, index + floatOffset);
             floatsToCPFloats.put(f, cpFloat);
@@ -527,7 +527,7 @@ public class CpBands extends BandSet {
         final String string = cpClass[index];
         final int utf8Index = cpClassInts[index];
         final int globalIndex = classOffset + index;
-        CPClass cpString = (CPClass) stringsToCPClass.get(string);
+        CPClass cpString = stringsToCPClass.get(string);
         if (cpString == null) {
             cpString = new CPClass(cpUTF8Value(utf8Index), globalIndex);
             stringsToCPClass.put(string, cpString);
@@ -536,9 +536,9 @@ public class CpBands extends BandSet {
     }
 
     public CPClass cpClassValue(final String string) {
-        CPClass cpString = (CPClass) stringsToCPClass.get(string);
+        CPClass cpString = stringsToCPClass.get(string);
         if (cpString == null) {
-            final Integer index = (Integer) mapClass.get(string);
+            final Integer index = mapClass.get(string);
             if (index != null) {
                 return cpClassValue(index.intValue());
             }
@@ -550,7 +550,7 @@ public class CpBands extends BandSet {
 
     public CPDouble cpDoubleValue(final int index) {
         final Double dbl = Double.valueOf(cpDouble[index]);
-        CPDouble cpDouble = (CPDouble) doublesToCPDoubles.get(dbl);
+        CPDouble cpDouble = doublesToCPDoubles.get(dbl);
         if (cpDouble == null) {
             cpDouble = new CPDouble(dbl, index + doubleOffset);
             doublesToCPDoubles.put(dbl, cpDouble);
@@ -560,7 +560,7 @@ public class CpBands extends BandSet {
 
     public CPNameAndType cpNameAndTypeValue(final int index) {
         final String descriptor = cpDescriptor[index];
-        CPNameAndType cpNameAndType = (CPNameAndType) descriptorsToCPNameAndTypes.get(descriptor);
+        CPNameAndType cpNameAndType = descriptorsToCPNameAndTypes.get(descriptor);
         if (cpNameAndType == null) {
             final int nameIndex = cpDescriptorNameInts[index];
             final int descriptorIndex = cpDescriptorTypeInts[index];
@@ -596,7 +596,7 @@ public class CpBands extends BandSet {
             globalIndex = index + signatureOffset;
         }
         final String string = cpSignature[index];
-        CPUTF8 cpUTF8 = (CPUTF8) stringsToCPUTF8.get(string);
+        CPUTF8 cpUTF8 = stringsToCPUTF8.get(string);
         if (cpUTF8 == null) {
             cpUTF8 = new CPUTF8(string, globalIndex);
             stringsToCPUTF8.put(string, cpUTF8);
@@ -605,9 +605,9 @@ public class CpBands extends BandSet {
     }
 
     public CPNameAndType cpNameAndTypeValue(final String descriptor) {
-        CPNameAndType cpNameAndType = (CPNameAndType) descriptorsToCPNameAndTypes.get(descriptor);
+        CPNameAndType cpNameAndType = descriptorsToCPNameAndTypes.get(descriptor);
         if (cpNameAndType == null) {
-            final Integer index = (Integer) mapDescriptor.get(descriptor);
+            final Integer index = mapDescriptor.get(descriptor);
             if (index != null) {
                 return cpNameAndTypeValue(index.intValue());
             }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/IcBands.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/IcBands.java
index 76f43cd0..89a2a7ea 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/IcBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/IcBands.java
@@ -29,6 +29,7 @@ import org.apache.commons.compress.harmony.pack200.Codec;
 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
 import org.apache.commons.compress.harmony.unpack200.bytecode.CPClass;
 import org.apache.commons.compress.harmony.unpack200.bytecode.ClassConstantPool;
+import org.apache.commons.compress.harmony.unpack200.bytecode.ClassFileEntry;
 import org.apache.commons.compress.harmony.unpack200.bytecode.ConstantPoolEntry;
 
 /**
@@ -42,8 +43,8 @@ public class IcBands extends BandSet {
 
     private final String[] cpClass;
 
-    private Map thisClassToTuple;
-    private Map outerClassToTuples;
+    private Map<String, IcTuple> thisClassToTuple;
+    private Map<String, List<IcTuple>> outerClassToTuples;
 
     /**
      * @param segment TODO
@@ -111,8 +112,8 @@ public class IcBands extends BandSet {
     @Override
     public void unpack() throws IOException, Pack200Exception {
         final IcTuple[] allTuples = getIcTuples();
-        thisClassToTuple = new HashMap(allTuples.length);
-        outerClassToTuples = new HashMap(allTuples.length);
+        thisClassToTuple = new HashMap<>(allTuples.length);
+        outerClassToTuples = new HashMap<>(allTuples.length);
         for (final IcTuple tuple : allTuples) {
 
             // generate mapping thisClassString -> IcTuple
@@ -132,9 +133,9 @@ public class IcBands extends BandSet {
 
                 // add tuple to corresponding bucket
                 final String key = tuple.outerClassString();
-                List bucket = (List) outerClassToTuples.get(key);
+                List<IcTuple> bucket = outerClassToTuples.get(key);
                 if (bucket == null) {
-                    bucket = new ArrayList();
+                    bucket = new ArrayList<>();
                     outerClassToTuples.put(key, bucket);
                 }
                 bucket.add(tuple);
@@ -154,19 +155,19 @@ public class IcBands extends BandSet {
      * @return array of IcTuple
      */
     public IcTuple[] getRelevantIcTuples(final String className, final ClassConstantPool cp) {
-        final Set relevantTuplesContains = new HashSet();
-        final List relevantTuples = new ArrayList();
+        final Set<IcTuple> relevantTuplesContains = new HashSet<>();
+        final List<IcTuple> relevantTuples = new ArrayList<>();
 
-        final List relevantCandidates = (List) outerClassToTuples.get(className);
+        final List<IcTuple> relevantCandidates = outerClassToTuples.get(className);
         if (relevantCandidates != null) {
             for (int index = 0; index < relevantCandidates.size(); index++) {
-                final IcTuple tuple = (IcTuple) relevantCandidates.get(index);
+                final IcTuple tuple = relevantCandidates.get(index);
                 relevantTuplesContains.add(tuple);
                 relevantTuples.add(tuple);
             }
         }
 
-        final List entries = cp.entries();
+        final List<ClassFileEntry> entries = cp.entries();
 
         // For every class constant in both ic_this_class and cp,
         // add it to ic_relevant. Repeat until no more
@@ -176,7 +177,7 @@ public class IcBands extends BandSet {
             final ConstantPoolEntry entry = (ConstantPoolEntry) entries.get(eIndex);
             if (entry instanceof CPClass) {
                 final CPClass clazz = (CPClass) entry;
-                final IcTuple relevant = (IcTuple) thisClassToTuple.get(clazz.name);
+                final IcTuple relevant = thisClassToTuple.get(clazz.name);
                 if (relevant != null && relevantTuplesContains.add(relevant)) {
                     relevantTuples.add(relevant);
                 }
@@ -189,15 +190,15 @@ public class IcBands extends BandSet {
         // added
         // as well.
 
-        final ArrayList tuplesToScan = new ArrayList(relevantTuples);
-        final ArrayList tuplesToAdd = new ArrayList();
+        final List<IcTuple> tuplesToScan = new ArrayList<>(relevantTuples);
+        final List<IcTuple> tuplesToAdd = new ArrayList<>();
 
         while (tuplesToScan.size() > 0) {
 
             tuplesToAdd.clear();
             for (int index = 0; index < tuplesToScan.size(); index++) {
-                final IcTuple aRelevantTuple = (IcTuple) tuplesToScan.get(index);
-                final IcTuple relevant = (IcTuple) thisClassToTuple.get(aRelevantTuple.outerClassString());
+                final IcTuple aRelevantTuple = tuplesToScan.get(index);
+                final IcTuple relevant = thisClassToTuple.get(aRelevantTuple.outerClassString());
                 if (relevant != null && !aRelevantTuple.outerIsAnonymous()) {
                     tuplesToAdd.add(relevant);
                 }
@@ -205,7 +206,7 @@ public class IcBands extends BandSet {
 
             tuplesToScan.clear();
             for (int index = 0; index < tuplesToAdd.size(); index++) {
-                final IcTuple tuple = (IcTuple) tuplesToAdd.get(index);
+                final IcTuple tuple = tuplesToAdd.get(index);
                 if (relevantTuplesContains.add(tuple)) {
                     relevantTuples.add(tuple);
                     tuplesToScan.add(tuple);
@@ -218,14 +219,14 @@ public class IcBands extends BandSet {
 
         // Now order the result as a subsequence of ic_all
         relevantTuples.sort((arg0, arg1) -> {
-            final Integer index1 = Integer.valueOf(((IcTuple) arg0).getTupleIndex());
-            final Integer index2 = Integer.valueOf(((IcTuple) arg1).getTupleIndex());
+            final Integer index1 = Integer.valueOf(arg0.getTupleIndex());
+            final Integer index2 = Integer.valueOf(arg1.getTupleIndex());
             return index1.compareTo(index2);
         });
 
         final IcTuple[] relevantTuplesArray = new IcTuple[relevantTuples.size()];
         for (int i = 0; i < relevantTuplesArray.length; i++) {
-            relevantTuplesArray[i] = (IcTuple) relevantTuples.get(i);
+            relevantTuplesArray[i] = relevantTuples.get(i);
         }
 
         return relevantTuplesArray;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/IcTuple.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/IcTuple.java
index 83832b62..df6c0b65 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/IcTuple.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/IcTuple.java
@@ -17,6 +17,7 @@
 package org.apache.commons.compress.harmony.unpack200;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * An IcTuple is the set of information that describes an inner class.
@@ -107,7 +108,7 @@ public class IcTuple {
      * @return TODO
      */
     public String[] innerBreakAtDollar(final String className) {
-        final ArrayList resultList = new ArrayList();
+        final List<String> resultList = new ArrayList<>();
         int start = 0;
         int index = 0;
         while (index < className.length()) {
@@ -123,7 +124,7 @@ public class IcTuple {
         }
         final String[] result = new String[resultList.size()];
         for (int i = 0; i < resultList.size(); i++) {
-            result[i] = (String) resultList.get(i);
+            result[i] = resultList.get(i);
         }
         return result;
     }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/MetadataBandGroup.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/MetadataBandGroup.java
index aaac3446..0b2307a2 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/MetadataBandGroup.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/MetadataBandGroup.java
@@ -68,7 +68,7 @@ public class MetadataBandGroup {
         this.cpBands = cpBands;
     }
 
-    private List attributes;
+    private List<Attribute> attributes;
 
     public int[] param_NB;
     public int[] anno_N;
@@ -113,18 +113,18 @@ public class MetadataBandGroup {
 
     private int nestpair_N_Index;
 
-    private Iterator nestname_RU_Iterator;
+    private Iterator<CPUTF8> nestname_RU_Iterator;
 
     private int anno_N_Index;
 
     private int pair_N_Index;
 
-    public List getAttributes() {
+    public List<Attribute> getAttributes() {
         // TODO: Optimize iterators!
         if (attributes == null) {
-            attributes = new ArrayList();
+            attributes = new ArrayList<>();
             if (name_RU != null) {
-                final Iterator name_RU_Iterator = Arrays.asList(name_RU).iterator();
+                final Iterator<CPUTF8> name_RU_Iterator = Arrays.asList(name_RU).iterator();
                 if (!type.equals("AD")) {
                     T_index = 0;
                 }
@@ -161,7 +161,7 @@ public class MetadataBandGroup {
     }
 
     private Attribute getAttribute(final int numAnnotations, final CPUTF8[] types, final int[] pairCounts,
-        final Iterator namesIterator) {
+        final Iterator<CPUTF8> namesIterator) {
         final Annotation[] annotations = new Annotation[numAnnotations];
         for (int i = 0; i < numAnnotations; i++) {
             annotations[i] = getAnnotation(types[i], pairCounts[i], namesIterator);
@@ -169,7 +169,7 @@ public class MetadataBandGroup {
         return new RuntimeVisibleorInvisibleAnnotationsAttribute(type.equals("RVA") ? rvaUTF8 : riaUTF8, annotations);
     }
 
-    private Attribute getParameterAttribute(final int numParameters, final Iterator namesIterator) {
+    private Attribute getParameterAttribute(final int numParameters, final Iterator<CPUTF8> namesIterator) {
         final ParameterAnnotation[] parameter_annotations = new ParameterAnnotation[numParameters];
         for (int i = 0; i < numParameters; i++) {
             final int numAnnotations = anno_N[anno_N_Index++];
@@ -184,11 +184,11 @@ public class MetadataBandGroup {
             parameter_annotations);
     }
 
-    private Annotation getAnnotation(final CPUTF8 type, final int pairCount, final Iterator namesIterator) {
+    private Annotation getAnnotation(final CPUTF8 type, final int pairCount, final Iterator<CPUTF8> namesIterator) {
         final CPUTF8[] elementNames = new CPUTF8[pairCount];
         final ElementValue[] elementValues = new ElementValue[pairCount];
         for (int j = 0; j < elementNames.length; j++) {
-            elementNames[j] = (CPUTF8) namesIterator.next();
+            elementNames[j] = namesIterator.next();
             final int t = T[T_index++];
             elementValues[j] = new ElementValue(t, getNextValue(t));
         }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
index f27a07ba..c4fa952e 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/NewAttributeBands.java
@@ -49,7 +49,7 @@ public class NewAttributeBands extends BandSet {
 
     private int backwardsCallCount;
 
-    protected List attributeLayoutElements;
+    protected List<AttributeLayoutElement> attributeLayoutElements;
 
     public NewAttributeBands(final Segment segment, final AttributeLayout attributeLayout) throws IOException {
         super(segment);
@@ -78,13 +78,12 @@ public class NewAttributeBands extends BandSet {
      * @throws IOException If an I/O error occurs.
      * @throws Pack200Exception TODO
      */
-    public List parseAttributes(final InputStream in, final int occurrenceCount) throws IOException, Pack200Exception {
-        for (Object attributeLayoutElement : attributeLayoutElements) {
-            final AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElement;
+    public List<Attribute> parseAttributes(final InputStream in, final int occurrenceCount) throws IOException, Pack200Exception {
+        for (AttributeLayoutElement element : attributeLayoutElements) {
             element.readBands(in, occurrenceCount);
         }
 
-        final List attributes = new ArrayList(occurrenceCount);
+        final List<Attribute> attributes = new ArrayList<>(occurrenceCount);
         for (int i = 0; i < occurrenceCount; i++) {
             attributes.add(getOneAttribute(i, attributeLayoutElements));
         }
@@ -98,11 +97,10 @@ public class NewAttributeBands extends BandSet {
      * @param elements TODO
      * @return attribute at the given index.
      */
-    private Attribute getOneAttribute(final int index, final List elements) {
+    private Attribute getOneAttribute(final int index, final List<AttributeLayoutElement> elements) {
         final NewAttribute attribute = new NewAttribute(segment.getCpBands().cpUTF8Value(attributeLayout.getName()),
             attributeLayout.getIndex());
-        for (Object element2 : elements) {
-            final AttributeLayoutElement element = (AttributeLayoutElement) element2;
+        for (AttributeLayoutElement element : elements) {
             element.addToAttribute(index, attribute);
         }
         return attribute;
@@ -115,7 +113,7 @@ public class NewAttributeBands extends BandSet {
      */
     private void parseLayout() throws IOException {
         if (attributeLayoutElements == null) {
-            attributeLayoutElements = new ArrayList();
+            attributeLayoutElements = new ArrayList<>();
             final StringReader stream = new StringReader(attributeLayout.getLayout());
             AttributeLayoutElement e;
             while ((e = readNextAttributeElement(stream)) != null) {
@@ -131,15 +129,14 @@ public class NewAttributeBands extends BandSet {
     private void resolveCalls() {
         int backwardsCalls = 0;
         for (int i = 0; i < attributeLayoutElements.size(); i++) {
-            final AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements.get(i);
+            final AttributeLayoutElement element = attributeLayoutElements.get(i);
             if (element instanceof Callable) {
                 final Callable callable = (Callable) element;
                 if (i == 0) {
                     callable.setFirstCallable(true);
                 }
-                final List body = callable.body; // Look for calls in the body
-                for (Object element2 : body) {
-                    final LayoutElement layoutElement = (LayoutElement) element2;
+                // Look for calls in the body
+                for (LayoutElement layoutElement : callable.body) {
                     // Set the callable for each call
                     backwardsCalls += resolveCallsForElement(i, callable, layoutElement);
                 }
@@ -158,7 +155,7 @@ public class NewAttributeBands extends BandSet {
                 call.setCallable(currentCallable);
             } else if (index > 0) { // Forwards call
                 for (int k = i + 1; k < attributeLayoutElements.size(); k++) {
-                    final AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements.get(k);
+                    final AttributeLayoutElement el = attributeLayoutElements.get(k);
                     if (el instanceof Callable) {
                         index--;
                         if (index == 0) {
@@ -170,7 +167,7 @@ public class NewAttributeBands extends BandSet {
             } else { // Backwards call
                 backwardsCalls++;
                 for (int k = i - 1; k >= 0; k--) {
-                    final AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements.get(k);
+                    final AttributeLayoutElement el = attributeLayoutElements.get(k);
                     if (el instanceof Callable) {
                         index++;
                         if (index == 0) {
@@ -181,10 +178,9 @@ public class NewAttributeBands extends BandSet {
                 }
             }
         } else if (layoutElement instanceof Replication) {
-            final List children = ((Replication) layoutElement).layoutElements;
-            for (Object child : children) {
-                final LayoutElement object = (LayoutElement) child;
-                backwardsCalls += resolveCallsForElement(i, currentCallable, object);
+            final List<LayoutElement> children = ((Replication) layoutElement).layoutElements;
+            for (LayoutElement child : children) {
+                backwardsCalls += resolveCallsForElement(i, currentCallable, child);
             }
         }
         return backwardsCalls;
@@ -246,7 +242,7 @@ public class NewAttributeBands extends BandSet {
             if (int_type.equals("S")) {
                 int_type += (char) stream.read();
             }
-            final List unionCases = new ArrayList();
+            final List<UnionCase> unionCases = new ArrayList<>();
             UnionCase c;
             while ((c = readNextUnionCase(stream)) != null) {
                 unionCases.add(c);
@@ -442,7 +438,7 @@ public class NewAttributeBands extends BandSet {
 
         private final Integral countElement;
 
-        private final List layoutElements = new ArrayList();
+        private final List<LayoutElement> layoutElements = new ArrayList<>();
 
         public Replication(final String tag, final String contents) throws IOException {
             this.countElement = new Integral(tag);
@@ -489,7 +485,7 @@ public class NewAttributeBands extends BandSet {
             return countElement;
         }
 
-        public List getLayoutElements() {
+        public List<LayoutElement> getLayoutElements() {
             return layoutElements;
         }
     }
@@ -500,12 +496,12 @@ public class NewAttributeBands extends BandSet {
     public class Union extends LayoutElement {
 
         private final Integral unionTag;
-        private final List unionCases;
+        private final List<UnionCase> unionCases;
         private final List<LayoutElement> defaultCaseBody;
         private int[] caseCounts;
         private int defaultCount;
 
-        public Union(final String tag, final List unionCases, final List<LayoutElement> body) {
+        public Union(final String tag, final List<UnionCase> unionCases, final List<LayoutElement> body) {
             this.unionTag = new Integral(tag);
             this.unionCases = unionCases;
             this.defaultCaseBody = body;
@@ -518,7 +514,7 @@ public class NewAttributeBands extends BandSet {
             // Count the band size for each union case then read the bands
             caseCounts = new int[unionCases.size()];
             for (int i = 0; i < caseCounts.length; i++) {
-                final UnionCase unionCase = (UnionCase) unionCases.get(i);
+                final UnionCase unionCase = unionCases.get(i);
                 for (int value : values) {
                     if (unionCase.hasTag(value)) {
                         caseCounts[i]++;
@@ -592,7 +588,7 @@ public class NewAttributeBands extends BandSet {
             return unionTag;
         }
 
-        public List getUnionCases() {
+        public List<UnionCase> getUnionCases() {
             return unionCases;
         }
 
@@ -799,7 +795,7 @@ public class NewAttributeBands extends BandSet {
             this.isFirstCallable = isFirstCallable;
         }
 
-        public List getBody() {
+        public List<LayoutElement> getBody() {
             return body;
         }
     }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/Segment.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/Segment.java
index f6091f56..6564cc21 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/Segment.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/Segment.java
@@ -126,10 +126,10 @@ public class Segment {
         // == str
 
         // Get the source file attribute
-        final ArrayList classAttributes = classBands.getClassAttributes()[classNum];
+        final List<Attribute> classAttributes = classBands.getClassAttributes()[classNum];
         SourceFileAttribute sourceFileAttribute = null;
-        for (Object classAttribute : classAttributes) {
-            if (((Attribute) classAttribute).isSourceFileAttribute()) {
+        for (Attribute classAttribute : classAttributes) {
+            if (classAttribute.isSourceFileAttribute()) {
                 sourceFileAttribute = ((SourceFileAttribute) classAttribute);
             }
         }
@@ -166,9 +166,9 @@ public class Segment {
         // that will
         // be written out. Keep SourceFileAttributes out since we just
         // did them above.
-        final ArrayList classAttributesWithoutSourceFileAttribute = new ArrayList(classAttributes.size());
+        final List<Attribute> classAttributesWithoutSourceFileAttribute = new ArrayList<>(classAttributes.size());
         for (int index = 0; index < classAttributes.size(); index++) {
-            final Attribute attrib = (Attribute) classAttributes.get(index);
+            final Attribute attrib = classAttributes.get(index);
             if (!attrib.isSourceFileAttribute()) {
                 classAttributesWithoutSourceFileAttribute.add(attrib);
             }
@@ -178,7 +178,7 @@ public class Segment {
             + classAttributesWithoutSourceFileAttribute.size()];
         System.arraycopy(originalAttributes, 0, classFile.attributes, 0, originalAttributes.length);
         for (int index = 0; index < classAttributesWithoutSourceFileAttribute.size(); index++) {
-            final Attribute attrib = ((Attribute) classAttributesWithoutSourceFileAttribute.get(index));
+            final Attribute attrib = (classAttributesWithoutSourceFileAttribute.get(index));
             cp.add(attrib);
             classFile.attributes[originalAttributes.length + index] = attrib;
         }
@@ -223,9 +223,8 @@ public class Segment {
         final boolean ic_local_sent = ic_local != null;
         final InnerClassesAttribute innerClassesAttribute = new InnerClassesAttribute("InnerClasses");
         final IcTuple[] ic_relevant = getIcBands().getRelevantIcTuples(fullName, cp);
-        final List ic_stored = computeIcStored(ic_local, ic_relevant);
-        for (Object element : ic_stored) {
-            final IcTuple icStored = (IcTuple) element;
+        final List<IcTuple> ic_stored = computeIcStored(ic_local, ic_relevant);
+        for (IcTuple icStored : ic_stored) {
             final int innerClassIndex = icStored.thisClassIndex();
             final int outerClassIndex = icStored.outerClassIndex();
             final int simpleClassNameIndex = icStored.simpleClassNameIndex();
@@ -300,10 +299,10 @@ public class Segment {
      * @return List of tuples to be stored. If ic_local is null or empty, the values returned may not be correct. The
      *         caller will have to determine if this is the case.
      */
-    private List computeIcStored(final IcTuple[] ic_local, final IcTuple[] ic_relevant) {
-        final List result = new ArrayList(ic_relevant.length);
-        final List duplicates = new ArrayList(ic_relevant.length);
-        final Set isInResult = new HashSet(ic_relevant.length);
+    private List<IcTuple> computeIcStored(final IcTuple[] ic_local, final IcTuple[] ic_relevant) {
+        final List<IcTuple> result = new ArrayList<>(ic_relevant.length);
+        final List<IcTuple> duplicates = new ArrayList<>(ic_relevant.length);
+        final Set<IcTuple> isInResult = new HashSet<>(ic_relevant.length);
 
         // need to compute:
         // result = ic_local XOR ic_relevant
@@ -328,7 +327,7 @@ public class Segment {
 
         // eliminate "duplicates"
         for (int index = 0; index < duplicates.size(); index++) {
-            final IcTuple tuple = (IcTuple) duplicates.get(index);
+            final IcTuple tuple = duplicates.get(index);
             result.remove(tuple);
         }
 
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPool.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPool.java
index 8e1e9d59..faadb980 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPool.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPool.java
@@ -204,7 +204,7 @@ public class SegmentConstantPool {
     protected int matchSpecificPoolEntryIndex(final String[] primaryArray, final String[] secondaryArray,
         final String primaryCompareString, final String secondaryCompareRegex, final int desiredIndex) {
         int instanceCount = -1;
-        final List indexList = arrayCache.indexesForArrayKey(primaryArray, primaryCompareString);
+        final List<Integer> indexList = arrayCache.indexesForArrayKey(primaryArray, primaryCompareString);
         if (indexList.isEmpty()) {
             // Primary key not found, no chance of finding secondary
             return -1;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPoolArrayCache.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPoolArrayCache.java
index 2f6a7f06..d5570da5 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPoolArrayCache.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/SegmentConstantPoolArrayCache.java
@@ -34,9 +34,9 @@ import java.util.List;
  */
 public class SegmentConstantPoolArrayCache {
 
-    protected IdentityHashMap knownArrays = new IdentityHashMap(1000);
+    protected IdentityHashMap<String[], CachedArray> knownArrays = new IdentityHashMap<>(1000);
 
-    protected List lastIndexes;
+    protected List<Integer> lastIndexes;
     protected String[] lastArray;
     protected String lastKey;
 
@@ -47,7 +47,7 @@ public class SegmentConstantPoolArrayCache {
      * @param key String value for which to search
      * @return List collection of index positions in the array
      */
-    public List indexesForArrayKey(final String[] array, final String key) {
+    public List<Integer> indexesForArrayKey(final String[] array, final String key) {
         if (!arrayIsCached(array)) {
             cacheArray(array);
         }
@@ -65,7 +65,7 @@ public class SegmentConstantPoolArrayCache {
         // Remember the last thing we found.
         lastArray = array;
         lastKey = key;
-        lastIndexes = ((CachedArray) knownArrays.get(array)).indexesForKey(key);
+        lastIndexes = knownArrays.get(array).indexesForKey(key);
 
         return lastIndexes;
     }
@@ -81,7 +81,7 @@ public class SegmentConstantPoolArrayCache {
         if (!knownArrays.containsKey(array)) {
             return false;
         }
-        final CachedArray cachedArray = (CachedArray) knownArrays.get(array);
+        final CachedArray cachedArray = knownArrays.get(array);
         if (cachedArray.lastKnownSize() != array.length) {
             return false;
         }
@@ -109,13 +109,13 @@ public class SegmentConstantPoolArrayCache {
     protected class CachedArray {
         String[] primaryArray;
         int lastKnownSize;
-        HashMap primaryTable;
+        HashMap<String, List<Integer>> primaryTable;
 
         public CachedArray(final String[] array) {
             super();
             this.primaryArray = array;
             this.lastKnownSize = array.length;
-            this.primaryTable = new HashMap(lastKnownSize);
+            this.primaryTable = new HashMap<>(lastKnownSize);
             cacheIndexes();
         }
 
@@ -137,11 +137,11 @@ public class SegmentConstantPoolArrayCache {
          * @param key String element of the array
          * @return List of indexes containing that key in the array.
          */
-        public List indexesForKey(final String key) {
+        public List<Integer> indexesForKey(final String key) {
             if (!primaryTable.containsKey(key)) {
                 return Collections.EMPTY_LIST;
             }
-            return (List) primaryTable.get(key);
+            return primaryTable.get(key);
         }
 
         /**
@@ -153,9 +153,9 @@ public class SegmentConstantPoolArrayCache {
             for (int index = 0; index < primaryArray.length; index++) {
                 final String key = primaryArray[index];
                 if (!primaryTable.containsKey(key)) {
-                    primaryTable.put(key, new ArrayList());
+                    primaryTable.put(key, new ArrayList<>());
                 }
-                ((ArrayList) primaryTable.get(key)).add(Integer.valueOf(index));
+                primaryTable.get(key).add(Integer.valueOf(index));
             }
         }
     }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationDefaultAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationDefaultAttribute.java
index 104dabf5..b5f6a35f 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationDefaultAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationDefaultAttribute.java
@@ -67,7 +67,7 @@ public class AnnotationDefaultAttribute extends AnnotationsAttribute {
 
     @Override
     protected ClassFileEntry[] getNestedClassFileEntries() {
-        final List nested = new ArrayList();
+        final List<Object> nested = new ArrayList<>();
         nested.add(attributeName);
         nested.addAll(element_value.getClassFileEntries());
         final ClassFileEntry[] nestedEntries = new ClassFileEntry[nested.size()];
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationsAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationsAttribute.java
index 2cac234a..6dede86a 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationsAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/AnnotationsAttribute.java
@@ -77,8 +77,8 @@ public abstract class AnnotationsAttribute extends Attribute {
             }
         }
 
-        public List getClassFileEntries() {
-            final List entries = new ArrayList();
+        public List<Object> getClassFileEntries() {
+            final List<Object> entries = new ArrayList<>();
             for (int i = 0; i < element_names.length; i++) {
                 entries.add(element_names[i]);
                 entries.addAll(element_values[i].getClassFileEntries());
@@ -101,13 +101,14 @@ public abstract class AnnotationsAttribute extends Attribute {
             this.value = value;
         }
 
-        public List getClassFileEntries() {
-            final List entries = new ArrayList(1);
+        public List<Object> getClassFileEntries() {
+            final List<Object> entries = new ArrayList<>(1);
             if (value instanceof CPNameAndType) {
                 // used to represent enum, so don't include the actual CPNameAndType
                 entries.add(((CPNameAndType) value).name);
                 entries.add(((CPNameAndType) value).descriptor);
             } else if (value instanceof ClassFileEntry) {
+            	// TODO? ClassFileEntry is an Object
                 entries.add(value);
             } else if (value instanceof ElementValue[]) {
                 final ElementValue[] values = (ElementValue[]) value;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/BCIRenumberedAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/BCIRenumberedAttribute.java
index b3840c9d..14941724 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/BCIRenumberedAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/BCIRenumberedAttribute.java
@@ -62,14 +62,14 @@ public abstract class BCIRenumberedAttribute extends Attribute {
      * @param byteCodeOffsets List of Integer offsets of the bytecode array
      * @throws Pack200Exception TODO
      */
-    public void renumber(final List byteCodeOffsets) throws Pack200Exception {
+    public void renumber(final List<Integer> byteCodeOffsets) throws Pack200Exception {
         if (renumbered) {
             throw new Error("Trying to renumber a line number table that has already been renumbered");
         }
         renumbered = true;
         final int[] startPCs = getStartPCs();
         for (int index = 0; index < startPCs.length; index++) {
-            startPCs[index] = ((Integer) byteCodeOffsets.get(startPCs[index])).intValue();
+            startPCs[index] = byteCodeOffsets.get(startPCs[index]).intValue();
         }
     }
 
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPField.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPField.java
index ef11423a..5d25fa0c 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPField.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPField.java
@@ -23,7 +23,7 @@ import java.util.List;
  */
 public class CPField extends CPMember {
 
-    public CPField(final CPUTF8 name, final CPUTF8 descriptor, final long flags, final List attributes) {
+    public CPField(final CPUTF8 name, final CPUTF8 descriptor, final long flags, final List<Attribute> attributes) {
         super(name, descriptor, flags, attributes);
     }
 
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMember.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMember.java
index f05610d6..64616067 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMember.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMember.java
@@ -27,7 +27,7 @@ import java.util.Objects;
  */
 public class CPMember extends ClassFileEntry {
 
-    List attributes;
+    List<Attribute> attributes;
     short flags;
     CPUTF8 name;
     transient int nameIndex;
@@ -43,7 +43,7 @@ public class CPMember extends ClassFileEntry {
      * @param attributes TODO
      * @throws NullPointerException if name or descriptor is null
      */
-    public CPMember(final CPUTF8 name, final CPUTF8 descriptor, final long flags, final List attributes) {
+    public CPMember(final CPUTF8 name, final CPUTF8 descriptor, final long flags, final List<Attribute> attributes) {
         this.name = Objects.requireNonNull(name, "name");
         this.descriptor = Objects.requireNonNull(descriptor, "descriptor");
         this.flags = (short) flags;
@@ -57,7 +57,7 @@ public class CPMember extends ClassFileEntry {
         entries[0] = name;
         entries[1] = descriptor;
         for (int i = 0; i < attributeCount; i++) {
-            entries[i + 2] = (Attribute) attributes.get(i);
+            entries[i + 2] = attributes.get(i);
         }
         return entries;
     }
@@ -124,7 +124,7 @@ public class CPMember extends ClassFileEntry {
         final int attributeCount = attributes.size();
         dos.writeShort(attributeCount);
         for (int i = 0; i < attributeCount; i++) {
-            final Attribute attribute = (Attribute) attributes.get(i);
+            final Attribute attribute = attributes.get(i);
             attribute.doWrite(dos);
         }
     }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMethod.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMethod.java
index 3e0bbb45..f33f4686 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMethod.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CPMethod.java
@@ -23,7 +23,7 @@ import java.util.List;
  */
 public class CPMethod extends CPMember {
 
-    public CPMethod(final CPUTF8 name, final CPUTF8 descriptor, final long flags, final List attributes) {
+    public CPMethod(final CPUTF8 name, final CPUTF8 descriptor, final long flags, final List<Attribute> attributes) {
         super(name, descriptor, flags, attributes);
     }
 
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ClassConstantPool.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ClassConstantPool.java
index 2954da7c..9b43ce85 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ClassConstantPool.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ClassConstantPool.java
@@ -33,15 +33,15 @@ import org.apache.commons.compress.harmony.unpack200.Segment;
  */
 public class ClassConstantPool {
 
-    protected HashSet entriesContainsSet = new HashSet();
-    protected HashSet othersContainsSet = new HashSet();
+    protected HashSet<ClassFileEntry> entriesContainsSet = new HashSet<>();
+    protected HashSet<ClassFileEntry> othersContainsSet = new HashSet<>();
 
-    private final HashSet mustStartClassPool = new HashSet();
+    private final HashSet<ClassFileEntry> mustStartClassPool = new HashSet<>();
 
-    protected Map indexCache;
+    protected Map<ClassFileEntry, Integer> indexCache;
 
-    private final List others = new ArrayList(500);
-    private final List entries = new ArrayList(500);
+    private final List<ClassFileEntry> others = new ArrayList<>(500);
+    private final List<ClassFileEntry> entries = new ArrayList<>(500);
 
     private boolean resolved;
 
@@ -64,8 +64,8 @@ public class ClassConstantPool {
         boolean added = true;
 
         // initial assignment
-        final ArrayList parents = new ArrayList(512);
-        final ArrayList children = new ArrayList(512);
+        final List<ClassFileEntry> parents = new ArrayList<>(512);
+        final List<ClassFileEntry> children = new ArrayList<>(512);
 
         // adding old entries
         parents.addAll(entries);
@@ -83,7 +83,7 @@ public class ClassConstantPool {
             // get the parents' children and add them to buffer
             // concurrently add parents to target storage
             for (int indexParents = 0; indexParents < parents.size(); indexParents++) {
-                final ClassFileEntry entry = (ClassFileEntry) parents.get(indexParents);
+                final ClassFileEntry entry = parents.get(indexParents);
 
                 // traverse children
                 final ClassFileEntry[] entryChildren = entry.getNestedClassFileEntries();
@@ -115,7 +115,7 @@ public class ClassConstantPool {
         if (null == indexCache) {
             throw new IllegalStateException("Index cache is not initialized!");
         }
-        final Integer entryIndex = ((Integer) indexCache.get(entry));
+        final Integer entryIndex = (indexCache.get(entry));
         // If the entry isn't found, answer -1. Otherwise answer the entry.
         if (entryIndex != null) {
             return entryIndex.intValue() + 1;
@@ -131,7 +131,7 @@ public class ClassConstantPool {
         if (!resolved) {
             throw new IllegalStateException("Constant pool is not yet resolved; this does not make any sense");
         }
-        return (ClassFileEntry) entries.get(--i);
+        return entries.get(--i);
     }
 
     public void resolve(final Segment segment) {
@@ -140,27 +140,25 @@ public class ClassConstantPool {
 
         resolved = true;
 
-        for (Object entry2 : entries) {
-            final ClassFileEntry entry = (ClassFileEntry) entry2;
+        for (ClassFileEntry entry : entries) {
             entry.resolve(this);
         }
 
-        for (Object other : others) {
-            final ClassFileEntry entry = (ClassFileEntry) other;
-            entry.resolve(this);
+        for (ClassFileEntry other : others) {
+            other.resolve(this);
         }
 
     }
 
     private void initialSort() {
-        final TreeSet inCpAll = new TreeSet(
+        final TreeSet<ClassFileEntry> inCpAll = new TreeSet<>(
                 Comparator.comparingInt(arg0 -> ((ConstantPoolEntry) arg0).getGlobalIndex()));
-        final TreeSet cpUtf8sNotInCpAll = new TreeSet(
+        final TreeSet<ClassFileEntry> cpUtf8sNotInCpAll = new TreeSet<>(
                 Comparator.comparing(arg0 -> ((CPUTF8) arg0).underlyingString()));
-        final TreeSet cpClassesNotInCpAll = new TreeSet(
+        final TreeSet<ClassFileEntry> cpClassesNotInCpAll = new TreeSet<>(
                 Comparator.comparing(arg0 -> ((CPClass) arg0).getName()));
 
-        for (Object entry2 : entries) {
+        for (ClassFileEntry entry2 : entries) {
             final ConstantPoolEntry entry = (ConstantPoolEntry) entry2;
             if (entry.getGlobalIndex() == -1) {
                 if (entry instanceof CPUTF8) {
@@ -180,7 +178,7 @@ public class ClassConstantPool {
         entries.addAll(cpClassesNotInCpAll);
     }
 
-    public List entries() {
+    public List<ClassFileEntry> entries() {
         return Collections.unmodifiableList(entries);
     }
 
@@ -190,21 +188,20 @@ public class ClassConstantPool {
         // references to objects which need to be at the
         // start of the class pool
 
-        final ArrayList startOfPool = new ArrayList(entries.size());
-        final ArrayList finalSort = new ArrayList(entries.size());
+        final List<ClassFileEntry> startOfPool = new ArrayList<>(entries.size());
+        final List<ClassFileEntry> finalSort = new ArrayList<>(entries.size());
 
-        for (Object entry : entries) {
-            final ClassFileEntry nextEntry = (ClassFileEntry) entry;
-            if (mustStartClassPool.contains(nextEntry)) {
-                startOfPool.add(nextEntry);
+        for (ClassFileEntry entry : entries) {
+            if (mustStartClassPool.contains(entry)) {
+                startOfPool.add(entry);
             } else {
-                finalSort.add(nextEntry);
+                finalSort.add(entry);
             }
         }
 
         // copy over and rebuild the cache
         //
-        indexCache = new HashMap(entries.size());
+        indexCache = new HashMap<>(entries.size());
         int index = 0;
 
         entries.clear();
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CodeAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CodeAttribute.java
index 34b412d6..72be6986 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CodeAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/CodeAttribute.java
@@ -25,18 +25,18 @@ import org.apache.commons.compress.harmony.unpack200.Segment;
 
 public class CodeAttribute extends BCIRenumberedAttribute {
 
-    public List attributes = new ArrayList();
+    public List<Attribute> attributes = new ArrayList<>();
     // instances
-    public List byteCodeOffsets = new ArrayList();
-    public List byteCodes = new ArrayList();
+    public List<Integer> byteCodeOffsets = new ArrayList<>();
+    public List<ByteCode> byteCodes = new ArrayList<>();
     public int codeLength;
-    public List exceptionTable; // of ExceptionTableEntry
+    public List<ExceptionTableEntry> exceptionTable;
     public int maxLocals;
     public int maxStack;
     private static CPUTF8 attributeName;
 
     public CodeAttribute(final int maxStack, final int maxLocals, final byte[] codePacked, final Segment segment,
-        final OperandManager operandManager, final List exceptionTable) {
+        final OperandManager operandManager, final List<ExceptionTableEntry> exceptionTable) {
         super(attributeName);
         this.maxLocals = maxLocals;
         this.maxStack = maxStack;
@@ -53,7 +53,7 @@ public class CodeAttribute extends BCIRenumberedAttribute {
             byteCode.extractOperands(operandManager, segment, codeLength);
             byteCodes.add(byteCode);
             codeLength += byteCode.getLength();
-            final int lastBytecodePosition = ((Integer) byteCodeOffsets.get(byteCodeOffsets.size() - 1)).intValue();
+            final int lastBytecodePosition = byteCodeOffsets.get(byteCodeOffsets.size() - 1).intValue();
             // This code assumes all multiple byte bytecodes are
             // replaced by a single-byte bytecode followed by
             // another bytecode.
@@ -78,8 +78,7 @@ public class CodeAttribute extends BCIRenumberedAttribute {
         // sizes, fix up the byte code targets
         // At this point, byteCodes may be a different size than
         // codePacked because of wide bytecodes.
-        for (Object byteCode2 : byteCodes) {
-            final ByteCode byteCode = (ByteCode) byteCode2;
+        for (ByteCode byteCode : byteCodes) {
             byteCode.applyByteCodeTargetFixup(this);
         }
     }
@@ -96,13 +95,12 @@ public class CodeAttribute extends BCIRenumberedAttribute {
 
     @Override
     protected ClassFileEntry[] getNestedClassFileEntries() {
-        final ArrayList nestedEntries = new ArrayList(attributes.size() + byteCodes.size() + 10);
+        final List<ClassFileEntry> nestedEntries = new ArrayList<>(attributes.size() + byteCodes.size() + 10);
         nestedEntries.add(getAttributeName());
         nestedEntries.addAll(byteCodes);
         nestedEntries.addAll(attributes);
         // Don't forget to add the ExceptionTable catch_types
-        for (Object element : exceptionTable) {
-            final ExceptionTableEntry entry = (ExceptionTableEntry) element;
+        for (ExceptionTableEntry entry : exceptionTable) {
             final CPClass catchType = entry.getCatchType();
             // If the catch type is null, this is a finally
             // block. If it's not null, we need to add the
@@ -146,8 +144,7 @@ public class CodeAttribute extends BCIRenumberedAttribute {
         dos.writeShort(maxLocals);
 
         dos.writeInt(codeLength);
-        for (Object byteCode2 : byteCodes) {
-            final ByteCode byteCode = (ByteCode) byteCode2;
+        for (ByteCode byteCode : byteCodes) {
             byteCode.write(dos);
         }
 
@@ -181,9 +178,8 @@ public class CodeAttribute extends BCIRenumberedAttribute {
     }
 
     @Override
-    public void renumber(final List byteCodeOffsets) {
-        for (Object element : exceptionTable) {
-            final ExceptionTableEntry entry = (ExceptionTableEntry) element;
+    public void renumber(final List<Integer> byteCodeOffsets) {
+        for (ExceptionTableEntry entry : exceptionTable) {
             entry.renumber(byteCodeOffsets);
         }
     }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ExceptionTableEntry.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ExceptionTableEntry.java
index 01c1d446..f28b2922 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ExceptionTableEntry.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/ExceptionTableEntry.java
@@ -61,12 +61,12 @@ public class ExceptionTableEntry {
         dos.writeShort(catchTypeIndex);
     }
 
-    public void renumber(final List byteCodeOffsets) {
-        startPcRenumbered = ((Integer) byteCodeOffsets.get(startPC)).intValue();
+    public void renumber(final List<Integer> byteCodeOffsets) {
+        startPcRenumbered = byteCodeOffsets.get(startPC).intValue();
         final int endPcIndex = startPC + endPC;
-        endPcRenumbered = ((Integer) byteCodeOffsets.get(endPcIndex)).intValue();
+        endPcRenumbered = byteCodeOffsets.get(endPcIndex).intValue();
         final int handlerPcIndex = endPcIndex + handlerPC;
-        handlerPcRenumbered = ((Integer) byteCodeOffsets.get(handlerPcIndex)).intValue();
+        handlerPcRenumbered = byteCodeOffsets.get(handlerPcIndex).intValue();
     }
 
     public CPClass getCatchType() {
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/InnerClassesAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/InnerClassesAttribute.java
index ba4b565f..358a3944 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/InnerClassesAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/InnerClassesAttribute.java
@@ -88,8 +88,8 @@ public class InnerClassesAttribute extends Attribute {
 
     }
 
-    private final List innerClasses = new ArrayList();
-    private final List nestedClassFileEntries = new ArrayList();
+    private final List<InnerClassesEntry> innerClasses = new ArrayList<>();
+    private final List<ConstantPoolEntry> nestedClassFileEntries = new ArrayList<>();
 
     public InnerClassesAttribute(final String name) {
         super(attributeName);
@@ -127,7 +127,7 @@ public class InnerClassesAttribute extends Attribute {
     protected ClassFileEntry[] getNestedClassFileEntries() {
         final ClassFileEntry[] result = new ClassFileEntry[nestedClassFileEntries.size()];
         for (int index = 0; index < result.length; index++) {
-            result[index] = (ClassFileEntry) nestedClassFileEntries.get(index);
+            result[index] = nestedClassFileEntries.get(index);
         }
         return result;
     }
@@ -143,8 +143,7 @@ public class InnerClassesAttribute extends Attribute {
     @Override
     protected void resolve(final ClassConstantPool pool) {
         super.resolve(pool);
-        for (Object element : innerClasses) {
-            final InnerClassesEntry entry = (InnerClassesEntry) element;
+        for (InnerClassesEntry entry : innerClasses) {
             entry.resolve(pool);
         }
     }
@@ -164,8 +163,7 @@ public class InnerClassesAttribute extends Attribute {
     protected void writeBody(final DataOutputStream dos) throws IOException {
         dos.writeShort(innerClasses.size());
 
-        for (Object element : innerClasses) {
-            final InnerClassesEntry entry = (InnerClassesEntry) element;
+        for (InnerClassesEntry entry : innerClasses) {
             entry.write(dos);
         }
     }
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTableAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTableAttribute.java
index 8de1ea3f..0c9c48a5 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTableAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTableAttribute.java
@@ -77,7 +77,7 @@ public class LocalVariableTableAttribute extends BCIRenumberedAttribute {
 
     @Override
     protected ClassFileEntry[] getNestedClassFileEntries() {
-        final ArrayList nestedEntries = new ArrayList();
+        final List<CPUTF8> nestedEntries = new ArrayList<>();
         nestedEntries.add(getAttributeName());
         for (int i = 0; i < local_variable_table_length; i++) {
             nestedEntries.add(names[i]);
@@ -117,7 +117,7 @@ public class LocalVariableTableAttribute extends BCIRenumberedAttribute {
      * @see org.apache.commons.compress.harmony.unpack200.bytecode.BCIRenumberedAttribute#renumber(java.util.List)
      */
     @Override
-    public void renumber(final List byteCodeOffsets) throws Pack200Exception {
+    public void renumber(final List<Integer> byteCodeOffsets) throws Pack200Exception {
         // Remember the unrenumbered start_pcs, since that's used later
         // to calculate end position.
         final int[] unrenumbered_start_pcs = new int[start_pcs.length];
@@ -159,7 +159,7 @@ public class LocalVariableTableAttribute extends BCIRenumberedAttribute {
                 revisedLength = maxSize - start_pc;
             } else {
                 // We're indexed into the byte code array
-                final int stopValue = ((Integer) byteCodeOffsets.get(stopIndex)).intValue();
+                final int stopValue = byteCodeOffsets.get(stopIndex).intValue();
                 revisedLength = stopValue - start_pc;
             }
             lengths[index] = revisedLength;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTypeTableAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTypeTableAttribute.java
index 2912f90a..514eb143 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTypeTableAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/LocalVariableTypeTableAttribute.java
@@ -90,7 +90,7 @@ public class LocalVariableTypeTableAttribute extends BCIRenumberedAttribute {
 
     @Override
     protected ClassFileEntry[] getNestedClassFileEntries() {
-        final ArrayList nestedEntries = new ArrayList();
+        final List<CPUTF8> nestedEntries = new ArrayList<>();
         nestedEntries.add(getAttributeName());
         for (int i = 0; i < local_variable_type_table_length; i++) {
             nestedEntries.add(names[i]);
@@ -112,7 +112,7 @@ public class LocalVariableTypeTableAttribute extends BCIRenumberedAttribute {
      * @see org.apache.commons.compress.harmony.unpack200.bytecode.BCIRenumberedAttribute#renumber(java.util.List)
      */
     @Override
-    public void renumber(final List byteCodeOffsets) throws Pack200Exception {
+    public void renumber(final List<Integer> byteCodeOffsets) throws Pack200Exception {
         // Remember the unrenumbered start_pcs, since that's used later
         // to calculate end position.
         final int[] unrenumbered_start_pcs = new int[start_pcs.length];
@@ -154,7 +154,7 @@ public class LocalVariableTypeTableAttribute extends BCIRenumberedAttribute {
                 revisedLength = maxSize - start_pc;
             } else {
                 // We're indexed into the byte code array
-                final int stopValue = ((Integer) byteCodeOffsets.get(stopIndex)).intValue();
+                final int stopValue = byteCodeOffsets.get(stopIndex).intValue();
                 revisedLength = stopValue - start_pc;
             }
             lengths[index] = revisedLength;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/NewAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/NewAttribute.java
index a1e25abe..1b3220eb 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/NewAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/NewAttribute.java
@@ -26,8 +26,8 @@ import java.util.List;
  */
 public class NewAttribute extends BCIRenumberedAttribute {
 
-    private final List lengths = new ArrayList(); // List of Integers
-    private final List body = new ArrayList();
+    private final List<Integer> lengths = new ArrayList<>();
+    private final List<Object> body = new ArrayList<>();
     private ClassConstantPool pool;
     private final int layoutIndex;
 
@@ -48,8 +48,8 @@ public class NewAttribute extends BCIRenumberedAttribute {
     @Override
     protected int getLength() {
         int length = 0;
-        for (Object length2 : lengths) {
-            length += ((Integer) length2).intValue();
+        for (Integer len : lengths) {
+            length += len.intValue();
         }
         return length;
     }
@@ -62,7 +62,7 @@ public class NewAttribute extends BCIRenumberedAttribute {
     @Override
     protected void writeBody(final DataOutputStream dos) throws IOException {
         for (int i = 0; i < lengths.size(); i++) {
-            final int length = ((Integer) lengths.get(i)).intValue();
+            final int length = lengths.get(i).intValue();
             final Object obj = body.get(i);
             long value = 0;
             if (obj instanceof Long) {
@@ -202,33 +202,33 @@ public class NewAttribute extends BCIRenumberedAttribute {
     }
 
     @Override
-    public void renumber(final List byteCodeOffsets) {
+    public void renumber(final List<Integer> byteCodeOffsets) {
         if (!renumbered) {
             Object previous = null;
             for (Object obj : body) {
                 if (obj instanceof BCIndex) {
                     final BCIndex bcIndex = (BCIndex) obj;
-                    bcIndex.setActualValue(((Integer) byteCodeOffsets.get(bcIndex.index)).intValue());
+                    bcIndex.setActualValue(byteCodeOffsets.get(bcIndex.index).intValue());
                 } else if (obj instanceof BCOffset) {
                     final BCOffset bcOffset = (BCOffset) obj;
                     if (previous instanceof BCIndex) {
                         final int index = ((BCIndex) previous).index + bcOffset.offset;
                         bcOffset.setIndex(index);
-                        bcOffset.setActualValue(((Integer) byteCodeOffsets.get(index)).intValue());
+                        bcOffset.setActualValue(byteCodeOffsets.get(index).intValue());
                     } else if (previous instanceof BCOffset) {
                         final int index = ((BCOffset) previous).index + bcOffset.offset;
                         bcOffset.setIndex(index);
-                        bcOffset.setActualValue(((Integer) byteCodeOffsets.get(index)).intValue());
+                        bcOffset.setActualValue(byteCodeOffsets.get(index).intValue());
                     } else {
                         // Not sure if this should be able to happen
-                        bcOffset.setActualValue(((Integer) byteCodeOffsets.get(bcOffset.offset)).intValue());
+                        bcOffset.setActualValue(byteCodeOffsets.get(bcOffset.offset).intValue());
                     }
                 } else if (obj instanceof BCLength) {
                     // previous must be a BCIndex
                     final BCLength bcLength = (BCLength) obj;
                     final BCIndex prevIndex = (BCIndex) previous;
                     final int index = prevIndex.index + bcLength.length;
-                    final int actualLength = ((Integer) byteCodeOffsets.get(index)).intValue() - prevIndex.actualValue;
+                    final int actualLength = byteCodeOffsets.get(index).intValue() - prevIndex.actualValue;
                     bcLength.setActualValue(actualLength);
                 }
                 previous = obj;
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java
index 18f50c42..4612d451 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java
@@ -72,7 +72,7 @@ public class RuntimeVisibleorInvisibleAnnotationsAttribute extends AnnotationsAt
 
     @Override
     protected ClassFileEntry[] getNestedClassFileEntries() {
-        final List nested = new ArrayList();
+        final List<Object> nested = new ArrayList<>();
         nested.add(attributeName);
         for (Annotation annotation : annotations) {
             nested.addAll(annotation.getClassFileEntries());
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java
index b762928d..d9be8098 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java
@@ -101,8 +101,8 @@ public class RuntimeVisibleorInvisibleParameterAnnotationsAttribute extends Anno
             return length;
         }
 
-        public List getClassFileEntries() {
-            final List nested = new ArrayList();
+        public List<Object> getClassFileEntries() {
+            final List<Object> nested = new ArrayList<>();
             for (Annotation annotation : annotations) {
                 nested.addAll(annotation.getClassFileEntries());
             }
@@ -113,7 +113,7 @@ public class RuntimeVisibleorInvisibleParameterAnnotationsAttribute extends Anno
 
     @Override
     protected ClassFileEntry[] getNestedClassFileEntries() {
-        final List nested = new ArrayList();
+        final List<Object> nested = new ArrayList<>();
         nested.add(attributeName);
         for (ParameterAnnotation parameter_annotation : parameter_annotations) {
             nested.addAll(parameter_annotation.getClassFileEntries());
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/LabelForm.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/LabelForm.java
index 82ed7d17..1b682343 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/LabelForm.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/LabelForm.java
@@ -50,9 +50,9 @@ public class LabelForm extends ByteCodeForm {
         final int originalTarget = byteCode.getByteCodeTargets()[0];
         final int sourceIndex = byteCode.getByteCodeIndex();
         final int absoluteInstructionTargetIndex = sourceIndex + originalTarget;
-        final int targetValue = ((Integer) codeAttribute.byteCodeOffsets.get(absoluteInstructionTargetIndex))
+        final int targetValue = codeAttribute.byteCodeOffsets.get(absoluteInstructionTargetIndex)
             .intValue();
-        final int sourceValue = ((Integer) codeAttribute.byteCodeOffsets.get(sourceIndex)).intValue();
+        final int sourceValue = codeAttribute.byteCodeOffsets.get(sourceIndex).intValue();
         // The operand is the difference between the source instruction
         // and the destination instruction.
         byteCode.setOperandSigned2Bytes(targetValue - sourceValue, 0);
diff --git a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/SwitchForm.java b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/SwitchForm.java
index 4c695eab..a1814771 100644
--- a/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/SwitchForm.java
+++ b/src/main/java/org/apache/commons/compress/harmony/unpack200/bytecode/forms/SwitchForm.java
@@ -41,10 +41,10 @@ public abstract class SwitchForm extends VariableInstructionForm {
         final int[] replacementTargets = new int[numberOfLabels];
 
         final int sourceIndex = byteCode.getByteCodeIndex();
-        final int sourceValue = ((Integer) codeAttribute.byteCodeOffsets.get(sourceIndex)).intValue();
+        final int sourceValue = codeAttribute.byteCodeOffsets.get(sourceIndex).intValue();
         for (int index = 0; index < numberOfLabels; index++) {
             final int absoluteInstructionTargetIndex = sourceIndex + originalTargets[index];
-            final int targetValue = ((Integer) codeAttribute.byteCodeOffsets.get(absoluteInstructionTargetIndex))
+            final int targetValue = codeAttribute.byteCodeOffsets.get(absoluteInstructionTargetIndex)
                 .intValue();
             replacementTargets[index] = targetValue - sourceValue;
         }
diff --git a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/ArchiveTest.java b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/ArchiveTest.java
index b7b4c8b1..d33d5937 100755
--- a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/ArchiveTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/ArchiveTest.java
@@ -297,10 +297,10 @@ public class ArchiveTest extends TestCase {
     }
 
     private void compareJarEntries(JarFile jarFile, JarFile jarFile2) {
-        Enumeration entries = jarFile.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
         while (entries.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
 
             String name = entry.getName();
@@ -311,10 +311,10 @@ public class ArchiveTest extends TestCase {
 
     private void compareFiles(JarFile jarFile, JarFile jarFile2)
             throws IOException {
-        Enumeration entries = jarFile.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
         while (entries.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
 
             String name = entry.getName();
diff --git a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/CodecEncodingTest.java b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/CodecEncodingTest.java
index 9617afd5..c69592c7 100644
--- a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/CodecEncodingTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/CodecEncodingTest.java
@@ -40,7 +40,7 @@ public class CodecEncodingTest extends TestCase {
         Codec defaultCodec = new BHSDCodec(2, 16, 0, 0);
         assertEquals(defaultCodec, CodecEncoding
                 .getCodec(0, null, defaultCodec));
-        Map map = new HashMap();
+        Map<Integer, String> map = new HashMap<>();
         // These are the canonical encodings specified by the Pack200 spec
         map.put(new Integer(1), "(1,256)");
         map.put(new Integer(2), "(1,256,1)");
diff --git a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PackingOptionsTest.java b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PackingOptionsTest.java
index f9ad89fa..68e76df5 100644
--- a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PackingOptionsTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PackingOptionsTest.java
@@ -81,13 +81,13 @@ public class PackingOptionsTest extends TestCase {
         JarFile jarFile2 = new JarFile(compareFile);
 
         // Check that both jars have the same entries in the same order
-        Enumeration entries = jarFile.entries();
-        Enumeration entries2 = jarFile2.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
+        Enumeration<JarEntry> entries2 = jarFile2.entries();
         while (entries.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
-            JarEntry entry2 = (JarEntry) entries2.nextElement();
+            JarEntry entry2 = entries2.nextElement();
             String name = entry.getName();
             String name2 = entry2.getName();
             assertEquals(name, name2);
@@ -128,9 +128,9 @@ public class PackingOptionsTest extends TestCase {
         entries2 = jarFile2.entries();
         boolean inOrder = true;
         while (entries.hasMoreElements()) {
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
-            JarEntry entry2 = (JarEntry) entries2.nextElement();
+            JarEntry entry2 = entries2.nextElement();
             String name = entry.getName();
             String name2 = entry2.getName();
             if (!name.equals(name2)) {
@@ -198,13 +198,13 @@ public class PackingOptionsTest extends TestCase {
         JarFile jarFile2 = new JarFile(compareFile);
 
         // Check that both jars have the same entries in the same order
-        Enumeration entries = jarFile.entries();
-        Enumeration entries2 = jarFile2.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
+        Enumeration<JarEntry> entries2 = jarFile2.entries();
         while (entries.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
-            JarEntry entry2 = (JarEntry) entries2.nextElement();
+            JarEntry entry2 = entries2.nextElement();
             String name = entry.getName();
             String name2 = entry2.getName();
             assertEquals(name, name2);
@@ -245,9 +245,9 @@ public class PackingOptionsTest extends TestCase {
         long modtime = -1;
         boolean sameAsOriginal = true;
         while (entries.hasMoreElements()) {
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
-            JarEntry entry2 = (JarEntry) entries2.nextElement();
+            JarEntry entry2 = entries2.nextElement();
             String name = entry.getName();
             if (!name.startsWith("META-INF")) {
                 if (modtime == -1) {
@@ -638,10 +638,10 @@ public class PackingOptionsTest extends TestCase {
     // }
 
     private void compareJarEntries(JarFile jarFile, JarFile jarFile2) {
-        Enumeration entries = jarFile.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
         while (entries.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
 
             String name = entry.getName();
@@ -652,10 +652,10 @@ public class PackingOptionsTest extends TestCase {
 
     private void compareFiles(JarFile jarFile, JarFile jarFile2)
             throws IOException {
-        Enumeration entries = jarFile.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
         while (entries.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
 
             String name = entry.getName();
diff --git a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PopulationCodecTest.java b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PopulationCodecTest.java
index 13c960b2..8979d5ab 100644
--- a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PopulationCodecTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/PopulationCodecTest.java
@@ -20,7 +20,6 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.apache.commons.compress.harmony.pack200.BHSDCodec;
 import org.apache.commons.compress.harmony.pack200.Codec;
 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
 import org.apache.commons.compress.harmony.pack200.PopulationCodec;
@@ -67,13 +66,13 @@ public class PopulationCodecTest extends TestCase {
 
     public void testEncodeSingleValue() {
         try {
-            new PopulationCodec(BHSDCodec.SIGNED5, BHSDCodec.SIGNED5, BHSDCodec.UDELTA5).encode(5);
+            new PopulationCodec(Codec.SIGNED5, Codec.SIGNED5, Codec.UDELTA5).encode(5);
             fail("Should not allow a single value to be encoded as we don't know which codec to use");
         } catch (Pack200Exception e) {
             // pass
         }
         try {
-            new PopulationCodec(BHSDCodec.SIGNED5, BHSDCodec.SIGNED5, BHSDCodec.UDELTA5).encode(5, 8);
+            new PopulationCodec(Codec.SIGNED5, Codec.SIGNED5, Codec.UDELTA5).encode(5, 8);
             fail("Should not allow a single value to be encoded as we don't know which codec to use");
         } catch (Pack200Exception e) {
             // pass
diff --git a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/RunCodecTest.java b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/RunCodecTest.java
index 278b6289..2e7ba000 100644
--- a/src/test/java/org/apache/commons/compress/harmony/pack200/tests/RunCodecTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/pack200/tests/RunCodecTest.java
@@ -18,7 +18,6 @@ package org.apache.commons.compress.harmony.pack200.tests;
 
 import java.io.ByteArrayInputStream;
 
-import org.apache.commons.compress.harmony.pack200.BHSDCodec;
 import org.apache.commons.compress.harmony.pack200.Codec;
 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
 import org.apache.commons.compress.harmony.pack200.PopulationCodec;
@@ -33,19 +32,19 @@ public class RunCodecTest extends TestCase {
 
     public void testRunCodec() {
         try {
-            new RunCodec(0, BHSDCodec.SIGNED5, BHSDCodec.UDELTA5);
+            new RunCodec(0, Codec.SIGNED5, Codec.UDELTA5);
             fail("Should not allow a k value of 0");
         } catch (Pack200Exception e) {
             // pass
         }
         try {
-            new RunCodec(10, null, BHSDCodec.UDELTA5);
+            new RunCodec(10, null, Codec.UDELTA5);
             fail("Should not allow a null codec");
         } catch (Pack200Exception e) {
             // pass
         }
         try {
-            new RunCodec(10, BHSDCodec.UDELTA5, null);
+            new RunCodec(10, Codec.UDELTA5, null);
             fail("Should not allow a null codec");
         } catch (Pack200Exception e) {
             // pass
@@ -150,13 +149,13 @@ public class RunCodecTest extends TestCase {
 
     public void testEncodeSingleValue() {
         try {
-            new RunCodec(10, BHSDCodec.SIGNED5, BHSDCodec.UDELTA5).encode(5);
+            new RunCodec(10, Codec.SIGNED5, Codec.UDELTA5).encode(5);
             fail("Should not allow a single value to be encoded as we don't know which codec to use");
         } catch (Pack200Exception e) {
             // pass
         }
         try {
-            new RunCodec(10, BHSDCodec.SIGNED5, BHSDCodec.UDELTA5).encode(5, 8);
+            new RunCodec(10, Codec.SIGNED5, Codec.UDELTA5).encode(5, 8);
             fail("Should not allow a single value to be encoded as we don't know which codec to use");
         } catch (Pack200Exception e) {
             // pass
diff --git a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/ArchiveTest.java b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/ArchiveTest.java
index 60af73bb..020987f8 100644
--- a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/ArchiveTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/ArchiveTest.java
@@ -87,15 +87,15 @@ public class ArchiveTest extends TestCase {
         assertTrue("Expected jar files to be a similar size, difference was "
                 + differenceInJarSizes + " bytes", differenceInJarSizes < 100);
 
-        Enumeration entries = jarFile.entries();
-        Enumeration entries2 = jarFile2.entries();
+        Enumeration<JarEntry> entries = jarFile.entries();
+        Enumeration<JarEntry> entries2 = jarFile2.entries();
         while(entries.hasMoreElements() && entries2.hasMoreElements()) {
 
-            JarEntry entry = (JarEntry) entries.nextElement();
+            JarEntry entry = entries.nextElement();
             assertNotNull(entry);
             String name = entry.getName();
 
-            JarEntry entry2 = (JarEntry) entries2.nextElement();
+            JarEntry entry2 = entries2.nextElement();
             assertNotNull(entry2);
             String name2 = entry2.getName();
 
diff --git a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/BcBandsTest.java b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/BcBandsTest.java
index 2a0b6717..7f89d214 100644
--- a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/BcBandsTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/BcBandsTest.java
@@ -221,8 +221,7 @@ public class BcBandsTest extends AbstractBandsTestCase {
             }
             ArrayList orderedAttributeList = new ArrayList();
             for (int classIndex = 0; classIndex < totalMethods; classIndex++) {
-                ArrayList currentAttributes = new ArrayList();
-                orderedAttributeList.add(currentAttributes);
+                orderedAttributeList.add(new ArrayList());
             }
             return orderedAttributeList;
         }
diff --git a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/CodeAttributeTest.java b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/CodeAttributeTest.java
index 0bcdb5eb..63c0348b 100644
--- a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/CodeAttributeTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/CodeAttributeTest.java
@@ -22,12 +22,12 @@ import java.util.List;
 import org.apache.commons.compress.harmony.unpack200.CpBands;
 import org.apache.commons.compress.harmony.unpack200.Segment;
 import org.apache.commons.compress.harmony.unpack200.SegmentConstantPool;
-import org.apache.commons.compress.harmony.unpack200.bytecode.ByteCode;
 import org.apache.commons.compress.harmony.unpack200.bytecode.CPFieldRef;
 import org.apache.commons.compress.harmony.unpack200.bytecode.CPMethodRef;
 import org.apache.commons.compress.harmony.unpack200.bytecode.CPString;
 import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8;
 import org.apache.commons.compress.harmony.unpack200.bytecode.CodeAttribute;
+import org.apache.commons.compress.harmony.unpack200.bytecode.ExceptionTableEntry;
 import org.apache.commons.compress.harmony.unpack200.bytecode.LocalVariableTableAttribute;
 import org.apache.commons.compress.harmony.unpack200.bytecode.OperandManager;
 
@@ -38,20 +38,18 @@ import junit.framework.TestCase;
  */
 public class CodeAttributeTest extends TestCase {
 
-    public class MockCodeAttribute extends CodeAttribute {
+	public class MockCodeAttribute extends CodeAttribute {
 
-        public MockCodeAttribute(int maxStack, int maxLocals,
-                byte[] codePacked, Segment segment,
-                OperandManager operandManager, List exceptionTable) {
-            super(maxStack, maxLocals, codePacked, segment, operandManager,
-                    exceptionTable);
-        }
+		public MockCodeAttribute(int maxStack, int maxLocals, byte[] codePacked, Segment segment,
+				OperandManager operandManager, List<ExceptionTableEntry> exceptionTable) {
+			super(maxStack, maxLocals, codePacked, segment, operandManager, exceptionTable);
+		}
 
-        @Override
-        public int getLength() {
-            return super.getLength();
-        }
-    }
+		@Override
+		public int getLength() {
+			return super.getLength();
+		}
+	}
 
     public class MockCpBands extends CpBands {
 
@@ -170,16 +168,16 @@ public class CodeAttributeTest extends TestCase {
                 mixedByteArray, // codePacked
                 segment, // segment
                 operandManager, // operandManager
-                new ArrayList());
+                new ArrayList<>());
         assertEquals(2, attribute.maxLocals);
         assertEquals(3, attribute.maxStack);
-        assertEquals("aload_0_putfield_this", ((ByteCode) attribute.byteCodes
-                .get(4)).toString());
+        assertEquals("aload_0_putfield_this", attribute.byteCodes
+                .get(4).toString());
 
         int expectedLabels[] = new int[] { 0, 1, 4, 5, 8, 9, 10, 13, 14 };
         for (int index = 0; index < expectedLabels.length; index++) {
             assertEquals(expectedLabels[index],
-                    ((Integer) attribute.byteCodeOffsets.get(index)).intValue());
+                    attribute.byteCodeOffsets.get(index).intValue());
         }
     }
 
@@ -193,16 +191,16 @@ public class CodeAttributeTest extends TestCase {
                 singleByteArray, // codePacked
                 segment, // segment
                 operandManager, // operandManager
-                new ArrayList());
+                new ArrayList<>());
         assertEquals(3, attribute.maxLocals);
         assertEquals(4, attribute.maxStack);
-        assertEquals("invokespecial_this", ((ByteCode) attribute.byteCodes
-                .get(3)).toString());
+        assertEquals("invokespecial_this", attribute.byteCodes
+                .get(3).toString());
 
         int expectedLabels[] = new int[] { 0, 1, 2, 4 };
         for (int index = 0; index < expectedLabels.length; index++) {
             assertEquals(expectedLabels[index],
-                    ((Integer) attribute.byteCodeOffsets.get(index)).intValue());
+                    attribute.byteCodeOffsets.get(index).intValue());
         }
     }
 
diff --git a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/NewAttributeBandsTest.java b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/NewAttributeBandsTest.java
index b7764d43..441ee194 100644
--- a/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/NewAttributeBandsTest.java
+++ b/src/test/java/org/apache/commons/compress/harmony/unpack200/tests/NewAttributeBandsTest.java
@@ -40,7 +40,7 @@ public class NewAttributeBandsTest extends AbstractBandsTestCase {
         MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(
                 new MockSegment(), new AttributeLayout("test",
                         AttributeLayout.CONTEXT_CLASS, "", 25));
-        List layoutElements = newAttributeBands.getLayoutElements();
+        List<?> layoutElements = newAttributeBands.getLayoutElements();
         assertEquals(0, layoutElements.size());
     }
 
@@ -249,7 +249,7 @@ public class NewAttributeBandsTest extends AbstractBandsTestCase {
             super(segment, layout);
         }
 
-        public List getLayoutElements() {
+        public List<?> getLayoutElements() {
             return attributeLayoutElements;
         }
     }