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 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;

import java.util.Arrays;

/**
 * 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