All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.classfile.editor.ConstantPoolShrinker Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2020 Guardsquare NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package proguard.classfile.editor;

import java.util.Arrays;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.annotation.visitor.*;
import proguard.classfile.attribute.module.*;
import proguard.classfile.attribute.module.visitor.*;
import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.preverification.visitor.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.visitor.*;
import proguard.util.Processable;

/**
 * This {@link ClassVisitor} removes all unused entries from the constant pool.
 *
 * @author Eric Lafortune
 */
public class ConstantPoolShrinker
    implements ClassVisitor,

        // Implementation interfaces.
        MemberVisitor,
        ConstantVisitor,
        AttributeVisitor,
        BootstrapMethodInfoVisitor,
        RecordComponentInfoVisitor,
        InnerClassesInfoVisitor,
        ExceptionInfoVisitor,
        StackMapFrameVisitor,
        VerificationTypeVisitor,
        ParameterInfoVisitor,
        LocalVariableInfoVisitor,
        LocalVariableTypeInfoVisitor,
        RequiresInfoVisitor,
        ExportsInfoVisitor,
        OpensInfoVisitor,
        ProvidesInfoVisitor,
        AnnotationVisitor,
        ElementValueVisitor,
        InstructionVisitor {
  // A processing info flag to indicate that the constant is being used.
  // Don't make a static instance, so we don't need to clear any old flags.
  private final Object USED = new Object();

  private int[] constantIndexMap = new int[ClassEstimates.TYPICAL_CONSTANT_POOL_SIZE];
  private final ConstantPoolRemapper constantPoolRemapper = new ConstantPoolRemapper();

  // Implementations for ClassVisitor.

  @Override
  public void visitAnyClass(Clazz clazz) {}

  @Override
  public void visitProgramClass(ProgramClass programClass) {
    // Remove any previous processing info from the constant pool entries.
    programClass.constantPoolEntriesAccept(new ClassCleaner());

    // Mark this class's name.
    markConstant(programClass, programClass.u2thisClass);

    // Mark the superclass class constant.
    programClass.superClassConstantAccept(this);

    // Mark the interface class constants.
    programClass.interfaceConstantsAccept(this);

    // Mark the constants referenced by the class members.
    programClass.fieldsAccept(this);
    programClass.methodsAccept(this);

    // Mark the attributes.
    programClass.attributesAccept(this);

    // Shift the used constant pool entries together, filling out the
    // index map.
    int newConstantPoolCount =
        shrinkConstantPool(programClass.constantPool, programClass.u2constantPoolCount);

    // Remap the references to the constant pool if it has shrunk.
    if (newConstantPoolCount < programClass.u2constantPoolCount) {
      programClass.u2constantPoolCount = newConstantPoolCount;

      // Remap all constant pool references.
      constantPoolRemapper.setConstantIndexMap(constantIndexMap);
      constantPoolRemapper.visitProgramClass(programClass);
    }
  }

  // Implementations for MemberVisitor.

  public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) {
    // Mark the name and descriptor.
    markConstant(programClass, programMember.u2nameIndex);
    markConstant(programClass, programMember.u2descriptorIndex);

    // Mark the attributes.
    programMember.attributesAccept(programClass, this);
  }

  // Implementations for ConstantVisitor.

  public void visitAnyConstant(Clazz clazz, Constant constant) {
    markAsUsed(constant);
  }

  public void visitStringConstant(Clazz clazz, StringConstant stringConstant) {
    markAsUsed(stringConstant);

    markConstant(clazz, stringConstant.u2stringIndex);
  }

  public void visitDynamicConstant(Clazz clazz, DynamicConstant dynamicConstant) {
    markAsUsed(dynamicConstant);

    markConstant(clazz, dynamicConstant.u2nameAndTypeIndex);

    // Mark the bootstrap methods attribute.
    clazz.attributesAccept(this);
  }

  public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) {
    markAsUsed(invokeDynamicConstant);

    markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);

    // Mark the bootstrap methods attribute.
    clazz.attributesAccept(this);
  }

  public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) {
    markAsUsed(methodHandleConstant);

    markConstant(clazz, methodHandleConstant.u2referenceIndex);
  }

  public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) {
    markAsUsed(refConstant);

    markConstant(clazz, refConstant.u2classIndex);
    markConstant(clazz, refConstant.u2nameAndTypeIndex);
  }

  public void visitClassConstant(Clazz clazz, ClassConstant classConstant) {
    markAsUsed(classConstant);

    markConstant(clazz, classConstant.u2nameIndex);
  }

  public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) {
    markAsUsed(methodTypeConstant);

    markConstant(clazz, methodTypeConstant.u2descriptorIndex);
  }

  public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) {
    markAsUsed(nameAndTypeConstant);

    markConstant(clazz, nameAndTypeConstant.u2nameIndex);
    markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
  }

  public void visitModuleConstant(Clazz clazz, ModuleConstant moduleConstant) {
    markAsUsed(moduleConstant);

    markConstant(clazz, moduleConstant.u2nameIndex);
  }

  public void visitPackageConstant(Clazz clazz, PackageConstant packageConstant) {
    markAsUsed(packageConstant);

    markConstant(clazz, packageConstant.u2nameIndex);
  }

  // Implementations for AttributeVisitor.

  public void visitAnyAttribute(Clazz clazz, Attribute attribute) {
    markConstant(clazz, attribute.u2attributeNameIndex);
  }

  public void visitBootstrapMethodsAttribute(
      Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) {
    markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);

    // Mark the bootstrap method entries.
    bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
  }

  public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) {
    markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
    markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
  }

  public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) {
    markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
    markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
  }

  public void visitRecordAttribute(Clazz clazz, RecordAttribute recordAttribute) {
    markConstant(clazz, recordAttribute.u2attributeNameIndex);

    // Mark the component entries.
    recordAttribute.componentsAccept(clazz, this);
  }

  public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) {
    markConstant(clazz, innerClassesAttribute.u2attributeNameIndex);

    // Mark the outer class entries.
    innerClassesAttribute.innerClassEntriesAccept(clazz, this);
  }

  public void visitEnclosingMethodAttribute(
      Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) {
    markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
    markConstant(clazz, enclosingMethodAttribute.u2classIndex);
    markOptionalConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
  }

  public void visitNestHostAttribute(Clazz clazz, NestHostAttribute nestHostAttribute) {
    markConstant(clazz, nestHostAttribute.u2attributeNameIndex);
    markConstant(clazz, nestHostAttribute.u2hostClassIndex);
  }

  public void visitNestMembersAttribute(Clazz clazz, NestMembersAttribute nestMembersAttribute) {
    markConstant(clazz, nestMembersAttribute.u2attributeNameIndex);

    // Mark the nest member class constants.
    nestMembersAttribute.memberClassConstantsAccept(clazz, this);
  }

  public void visitPermittedSubclassesAttribute(
      Clazz clazz, PermittedSubclassesAttribute permittedSubclassesAttribute) {
    markConstant(clazz, permittedSubclassesAttribute.u2attributeNameIndex);

    // Mark the nest member class constants.
    permittedSubclassesAttribute.permittedSubclassConstantsAccept(clazz, this);
  }

  public void visitModuleAttribute(Clazz clazz, ModuleAttribute moduleAttribute) {
    markConstant(clazz, moduleAttribute.u2attributeNameIndex);
    markConstant(clazz, moduleAttribute.u2moduleNameIndex);
    markOptionalConstant(clazz, moduleAttribute.u2moduleVersionIndex);

    // Mark the constant pool entries referenced by the contained info.
    moduleAttribute.requiresAccept(clazz, this);
    moduleAttribute.exportsAccept(clazz, this);
    moduleAttribute.opensAccept(clazz, this);

    markConstants(clazz, moduleAttribute.u2uses, moduleAttribute.u2usesCount);

    // Mark the constant pool entries referenced by the provides info.
    moduleAttribute.providesAccept(clazz, this);
  }

  public void visitModuleMainClassAttribute(
      Clazz clazz, ModuleMainClassAttribute moduleMainClassAttribute) {
    markConstant(clazz, moduleMainClassAttribute.u2attributeNameIndex);
    markConstant(clazz, moduleMainClassAttribute.u2mainClass);
  }

  public void visitModulePackagesAttribute(
      Clazz clazz, ModulePackagesAttribute modulePackagesAttribute) {
    markConstant(clazz, modulePackagesAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the packages info.
    modulePackagesAttribute.packagesAccept(clazz, this);
  }

  public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) {
    markConstant(clazz, signatureAttribute.u2attributeNameIndex);
    markConstant(clazz, signatureAttribute.u2signatureIndex);
  }

  public void visitConstantValueAttribute(
      Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) {
    markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
    markConstant(clazz, constantValueAttribute.u2constantValueIndex);
  }

  public void visitMethodParametersAttribute(
      Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) {
    markConstant(clazz, methodParametersAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the parameter information.
    methodParametersAttribute.parametersAccept(clazz, method, this);
  }

  public void visitExceptionsAttribute(
      Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) {
    markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the exceptions.
    exceptionsAttribute.exceptionEntriesAccept(clazz, this);
  }

  public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) {
    markConstant(clazz, codeAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the instructions,
    // by the exceptions, and by the attributes.
    codeAttribute.instructionsAccept(clazz, method, this);
    codeAttribute.exceptionsAccept(clazz, method, this);
    codeAttribute.attributesAccept(clazz, method, this);
  }

  public void visitStackMapAttribute(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      StackMapAttribute stackMapAttribute) {
    markConstant(clazz, stackMapAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the stack map frames.
    stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
  }

  public void visitStackMapTableAttribute(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      StackMapTableAttribute stackMapTableAttribute) {
    markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the stack map frames.
    stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
  }

  public void visitLocalVariableTableAttribute(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      LocalVariableTableAttribute localVariableTableAttribute) {
    markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the local variables.
    localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
  }

  public void visitLocalVariableTypeTableAttribute(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      LocalVariableTypeTableAttribute localVariableTypeTableAttribute) {
    markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the local variable types.
    localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
  }

  public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) {
    markConstant(clazz, annotationsAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the annotations.
    annotationsAttribute.annotationsAccept(clazz, this);
  }

  public void visitAnyParameterAnnotationsAttribute(
      Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) {
    markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the annotations.
    parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
  }

  public void visitAnnotationDefaultAttribute(
      Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) {
    markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);

    // Mark the constant pool entries referenced by the element value.
    annotationDefaultAttribute.defaultValueAccept(clazz, this);
  }

  // Implementations for BootstrapMethodInfoVisitor.

  public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) {
    markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);

    // Mark the constant pool entries referenced by the arguments.
    bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
  }

  // Implementations for RecordComponentInfoVisitor.

  public void visitRecordComponentInfo(Clazz clazz, RecordComponentInfo recordComponentInfo) {
    markConstant(clazz, recordComponentInfo.u2nameIndex);
    markConstant(clazz, recordComponentInfo.u2descriptorIndex);

    // Mark the constant pool entries referenced by the attributes.
    recordComponentInfo.attributesAccept(clazz, this);
  }

  // Implementations for InnerClassesInfoVisitor.

  public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) {
    // Mark the constant pool entries referenced by the contained info.
    innerClassesInfo.innerClassConstantAccept(clazz, this);
    innerClassesInfo.outerClassConstantAccept(clazz, this);
    innerClassesInfo.innerNameConstantAccept(clazz, this);
  }

  // Implementations for ExceptionInfoVisitor.

  public void visitExceptionInfo(
      Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) {
    markOptionalConstant(clazz, exceptionInfo.u2catchType);
  }

  // Implementations for StackMapFrameVisitor.

  public void visitAnyStackMapFrame(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      StackMapFrame stackMapFrame) {}

  public void visitSameOneFrame(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      SameOneFrame sameOneFrame) {
    // Mark the constant pool entries referenced by the verification types.
    sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
  }

  public void visitMoreZeroFrame(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      MoreZeroFrame moreZeroFrame) {
    // Mark the constant pool entries referenced by the verification types.
    moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
  }

  public void visitFullFrame(
      Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) {
    // Mark the constant pool entries referenced by the verification types.
    fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
    fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
  }

  // Implementations for VerificationTypeVisitor.

  public void visitAnyVerificationType(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      VerificationType verificationType) {}

  public void visitObjectType(
      Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) {
    markConstant(clazz, objectType.u2classIndex);
  }

  // Implementations for ParameterInfoVisitor.

  public void visitParameterInfo(
      Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) {
    markOptionalConstant(clazz, parameterInfo.u2nameIndex);
  }

  // Implementations for LocalVariableInfoVisitor.

  public void visitLocalVariableInfo(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      LocalVariableInfo localVariableInfo) {
    markConstant(clazz, localVariableInfo.u2nameIndex);
    markConstant(clazz, localVariableInfo.u2descriptorIndex);
  }

  // Implementations for LocalVariableTypeInfoVisitor.

  public void visitLocalVariableTypeInfo(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      LocalVariableTypeInfo localVariableTypeInfo) {
    markConstant(clazz, localVariableTypeInfo.u2nameIndex);
    markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
  }

  // Implementations for RequiresInfoVisitor.

  public void visitRequiresInfo(Clazz clazz, RequiresInfo requiresInfo) {
    markConstant(clazz, requiresInfo.u2requiresIndex);
    markOptionalConstant(clazz, requiresInfo.u2requiresVersionIndex);
  }

  // Implementations for ExportsInfoVisitor.

  public void visitExportsInfo(Clazz clazz, ExportsInfo exportsInfo) {
    markConstant(clazz, exportsInfo.u2exportsIndex);
    markConstants(clazz, exportsInfo.u2exportsToIndex, exportsInfo.u2exportsToCount);
  }

  // Implementations for OpensInfoVisitor.

  public void visitOpensInfo(Clazz clazz, OpensInfo opensInfo) {
    markConstant(clazz, opensInfo.u2opensIndex);
    markConstants(clazz, opensInfo.u2opensToIndex, opensInfo.u2opensToCount);
  }

  // Implementations for ProvidesInfoVisitor.

  public void visitProvidesInfo(Clazz clazz, ProvidesInfo providesInfo) {
    markConstant(clazz, providesInfo.u2providesIndex);
    markConstants(clazz, providesInfo.u2providesWithIndex, providesInfo.u2providesWithCount);
  }

  // Implementations for AnnotationVisitor.

  public void visitAnnotation(Clazz clazz, Annotation annotation) {
    markConstant(clazz, annotation.u2typeIndex);

    // Mark the constant pool entries referenced by the element values.
    annotation.elementValuesAccept(clazz, this);
  }

  // Implementations for ElementValueVisitor.

  public void visitConstantElementValue(
      Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) {
    markOptionalConstant(clazz, constantElementValue.u2elementNameIndex);
    markConstant(clazz, constantElementValue.u2constantValueIndex);
  }

  public void visitEnumConstantElementValue(
      Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) {
    markOptionalConstant(clazz, enumConstantElementValue.u2elementNameIndex);
    markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
    markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
  }

  public void visitClassElementValue(
      Clazz clazz, Annotation annotation, ClassElementValue classElementValue) {
    markOptionalConstant(clazz, classElementValue.u2elementNameIndex);
    markConstant(clazz, classElementValue.u2classInfoIndex);
  }

  public void visitAnnotationElementValue(
      Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) {
    markOptionalConstant(clazz, annotationElementValue.u2elementNameIndex);

    // Mark the constant pool entries referenced by the annotation.
    annotationElementValue.annotationAccept(clazz, this);
  }

  public void visitArrayElementValue(
      Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) {
    markOptionalConstant(clazz, arrayElementValue.u2elementNameIndex);

    // Mark the constant pool entries referenced by the element values.
    arrayElementValue.elementValuesAccept(clazz, annotation, this);
  }

  // Implementations for InstructionVisitor.

  public void visitAnyInstruction(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      Instruction instruction) {}

  public void visitConstantInstruction(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      ConstantInstruction constantInstruction) {
    markConstant(clazz, constantInstruction.constantIndex);
  }

  // Small utility methods.

  /**
   * Marks the specified constant pool entries of the given class. This includes visiting any
   * referenced objects.
   */
  private void markConstants(Clazz clazz, int[] constantIndices, int constantIndicesCount) {
    for (int index = 0; index < constantIndicesCount; index++) {
      markConstant(clazz, constantIndices[index]);
    }
  }

  /**
   * Marks the specified constant pool entry of the given class, if the index is not 0. This
   * includes visiting any referenced objects.
   */
  private void markOptionalConstant(Clazz clazz, int constantIndex) {
    if (constantIndex != 0) {
      markConstant(clazz, constantIndex);
    }
  }

  /**
   * Marks the specified constant pool entry of the given class. This includes visiting any
   * referenced objects.
   */
  private void markConstant(Clazz clazz, int constantIndex) {
    clazz.constantPoolEntryAccept(constantIndex, this);
  }

  /** Marks the given processable as being used. */
  private void markAsUsed(Constant constant) {
    constant.setProcessingInfo(USED);
  }

  /** Returns whether the given processable has been marked as being used. */
  private boolean isUsed(Processable processable) {
    return processable.getProcessingInfo() == USED;
  }

  /**
   * Removes all constants that are not marked as being used from the given constant pool.
   *
   * @return the new number of entries.
   */
  private int shrinkConstantPool(Constant[] constantPool, int length) {
    // Create a new index map, if necessary.
    if (constantIndexMap.length < length) {
      constantIndexMap = new int[length];
    }

    int counter = 1;
    boolean isUsed = false;

    // Shift the used constant pool entries together.
    for (int index = 1; index < length; index++) {
      Constant constant = constantPool[index];

      // Is the constant being used? Don't update the flag if this is the
      // second half of a long entry.
      if (constant != null) {
        isUsed = isUsed(constant);
      }

      if (isUsed) {
        // Remember the new index.
        constantIndexMap[index] = counter;

        // Shift the constant pool entry.
        constantPool[counter++] = constant;
      } else {
        // Remember an invalid index.
        constantIndexMap[index] = -1;
      }
    }

    // Clear the remaining constant pool elements.
    Arrays.fill(constantPool, counter, length, null);

    return counter;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy