FileDocCategorySizeDatePackage
ClassDataItem.javaAPI DocAndroid 5.1 API13641Thu Mar 12 22:18:30 GMT 2015com.android.dx.dex.file

ClassDataItem

public final class ClassDataItem extends OffsettedItem
Representation of all the parts of a Dalvik class that are generally "inflated" into an in-memory representation at runtime. Instances of this class are represented in a compact streamable form in a {@code dex} file, as opposed to a random-access form.

Fields Summary
private final com.android.dx.rop.cst.CstType
thisClass
{@code non-null;} what class this data is for, just for listing generation
private final ArrayList
staticFields
{@code non-null;} list of static fields
private final HashMap
staticValues
{@code non-null;} list of initial values for static fields
private final ArrayList
instanceFields
{@code non-null;} list of instance fields
private final ArrayList
directMethods
{@code non-null;} list of direct methods
private final ArrayList
virtualMethods
{@code non-null;} list of virtual methods
private com.android.dx.rop.cst.CstArray
staticValuesConstant
{@code null-ok;} static initializer list; set in {@link #addContents}
private byte[]
encodedForm
{@code null-ok;} encoded form, ready for writing to a file; set during {@link #place0}
Constructors Summary
public ClassDataItem(com.android.dx.rop.cst.CstType thisClass)
Constructs an instance. Its sets of members are initially empty.

param
thisClass {@code non-null;} what class this data is for, just for listing generation

        super(1, -1);

        if (thisClass == null) {
            throw new NullPointerException("thisClass == null");
        }

        this.thisClass = thisClass;
        this.staticFields = new ArrayList<EncodedField>(20);
        this.staticValues = new HashMap<EncodedField, Constant>(40);
        this.instanceFields = new ArrayList<EncodedField>(20);
        this.directMethods = new ArrayList<EncodedMethod>(20);
        this.virtualMethods = new ArrayList<EncodedMethod>(20);
        this.staticValuesConstant = null;
    
Methods Summary
public voidaddContents(DexFile file)
{@inheritDoc}

        if (!staticFields.isEmpty()) {
            getStaticValuesConstant(); // Force the fields to be sorted.
            for (EncodedField field : staticFields) {
                field.addContents(file);
            }
        }

        if (!instanceFields.isEmpty()) {
            Collections.sort(instanceFields);
            for (EncodedField field : instanceFields) {
                field.addContents(file);
            }
        }

        if (!directMethods.isEmpty()) {
            Collections.sort(directMethods);
            for (EncodedMethod method : directMethods) {
                method.addContents(file);
            }
        }

        if (!virtualMethods.isEmpty()) {
            Collections.sort(virtualMethods);
            for (EncodedMethod method : virtualMethods) {
                method.addContents(file);
            }
        }
    
public voidaddDirectMethod(EncodedMethod method)
Adds a direct ({@code static} and/or {@code private}) method.

param
method {@code non-null;} the method to add

        if (method == null) {
            throw new NullPointerException("method == null");
        }

        directMethods.add(method);
    
public voidaddInstanceField(EncodedField field)
Adds an instance field.

param
field {@code non-null;} the field to add

        if (field == null) {
            throw new NullPointerException("field == null");
        }

        instanceFields.add(field);
    
public voidaddStaticField(EncodedField field, com.android.dx.rop.cst.Constant value)
Adds a static field.

param
field {@code non-null;} the field to add
param
value {@code null-ok;} initial value for the field, if any

        if (field == null) {
            throw new NullPointerException("field == null");
        }

        if (staticValuesConstant != null) {
            throw new UnsupportedOperationException(
                    "static fields already sorted");
        }

        staticFields.add(field);
        staticValues.put(field, value);
    
public voidaddVirtualMethod(EncodedMethod method)
Adds a virtual method.

param
method {@code non-null;} the method to add

        if (method == null) {
            throw new NullPointerException("method == null");
        }

        virtualMethods.add(method);
    
public voiddebugPrint(java.io.Writer out, boolean verbose)
Prints out the contents of this instance, in a debugging-friendly way.

param
out {@code non-null;} where to output to
param
verbose whether to be verbose with the output

        PrintWriter pw = Writers.printWriterFor(out);

        int sz = staticFields.size();
        for (int i = 0; i < sz; i++) {
            pw.println("  sfields[" + i + "]: " + staticFields.get(i));
        }

        sz = instanceFields.size();
        for (int i = 0; i < sz; i++) {
            pw.println("  ifields[" + i + "]: " + instanceFields.get(i));
        }

        sz = directMethods.size();
        for (int i = 0; i < sz; i++) {
            pw.println("  dmeths[" + i + "]:");
            directMethods.get(i).debugPrint(pw, verbose);
        }

        sz = virtualMethods.size();
        for (int i = 0; i < sz; i++) {
            pw.println("  vmeths[" + i + "]:");
            virtualMethods.get(i).debugPrint(pw, verbose);
        }
    
private static voidencodeList(DexFile file, com.android.dx.util.AnnotatedOutput out, java.lang.String label, java.util.ArrayList list)
Helper for {@link #encodeOutput}, which writes out the given list. It also annotates the items (if any and if annotations are enabled).

param
file {@code non-null;} file this instance is part of
param
out {@code non-null;} where to write to
param
label {@code non-null;} the label for the purposes of annotation
param
list {@code non-null;} the list in question

        int size = list.size();
        int lastIndex = 0;

        if (size == 0) {
            return;
        }

        if (out.annotates()) {
            out.annotate(0, "  " + label + ":");
        }

        for (int i = 0; i < size; i++) {
            lastIndex = list.get(i).encode(file, out, lastIndex, i);
        }
    
private voidencodeOutput(DexFile file, com.android.dx.util.AnnotatedOutput out)
Writes out the encoded form of this instance.

param
file {@code non-null;} file this instance is part of
param
out {@code non-null;} where to write to

        boolean annotates = out.annotates();

        if (annotates) {
            out.annotate(0, offsetString() + " class data for " +
                    thisClass.toHuman());
        }

        encodeSize(file, out, "static_fields", staticFields.size());
        encodeSize(file, out, "instance_fields", instanceFields.size());
        encodeSize(file, out, "direct_methods", directMethods.size());
        encodeSize(file, out, "virtual_methods", virtualMethods.size());

        encodeList(file, out, "static_fields", staticFields);
        encodeList(file, out, "instance_fields", instanceFields);
        encodeList(file, out, "direct_methods", directMethods);
        encodeList(file, out, "virtual_methods", virtualMethods);

        if (annotates) {
            out.endAnnotation();
        }
    
private static voidencodeSize(DexFile file, com.android.dx.util.AnnotatedOutput out, java.lang.String label, int size)
Helper for {@link #encodeOutput}, which writes out the given size value, annotating it as well (if annotations are enabled).

param
file {@code non-null;} file this instance is part of
param
out {@code non-null;} where to write to
param
label {@code non-null;} the label for the purposes of annotation
param
size {@code >= 0;} the size to write

        if (out.annotates()) {
            out.annotate(String.format("  %-21s %08x", label + "_size:",
                            size));
        }

        out.writeUleb128(size);
    
public java.util.ArrayListgetMethods()
Gets all the methods in this class. The returned list is not linked in any way to the underlying lists contained in this instance, but the objects contained in the list are shared.

return
{@code non-null;} list of all methods

        int sz = directMethods.size() + virtualMethods.size();
        ArrayList<EncodedMethod> result = new ArrayList<EncodedMethod>(sz);

        result.addAll(directMethods);
        result.addAll(virtualMethods);

        return result;
    
public com.android.dx.rop.cst.CstArraygetStaticValuesConstant()
Gets a {@link CstArray} corresponding to {@link #staticValues} if it contains any non-zero non-{@code null} values.

return
{@code null-ok;} the corresponding constant or {@code null} if there are no values to encode

        if ((staticValuesConstant == null) && (staticFields.size() != 0)) {
            staticValuesConstant = makeStaticValuesConstant();
        }

        return staticValuesConstant;
    
public booleanisEmpty()
Returns whether this instance is empty.

return
{@code true} if this instance is empty or {@code false} if at least one element has been added to it

        return staticFields.isEmpty() && instanceFields.isEmpty()
            && directMethods.isEmpty() && virtualMethods.isEmpty();
    
public ItemTypeitemType()
{@inheritDoc}

        return ItemType.TYPE_CLASS_DATA_ITEM;
    
private com.android.dx.rop.cst.CstArraymakeStaticValuesConstant()
Gets a {@link CstArray} corresponding to {@link #staticValues} if it contains any non-zero non-{@code null} values.

return
{@code null-ok;} the corresponding constant or {@code null} if there are no values to encode

        // First sort the statics into their final order.
        Collections.sort(staticFields);

        /*
         * Get the size of staticValues minus any trailing zeros/nulls (both
         * nulls per se as well as instances of CstKnownNull).
         */

        int size = staticFields.size();
        while (size > 0) {
            EncodedField field = staticFields.get(size - 1);
            Constant cst = staticValues.get(field);
            if (cst instanceof CstLiteralBits) {
                // Note: CstKnownNull extends CstLiteralBits.
                if (((CstLiteralBits) cst).getLongBits() != 0) {
                    break;
                }
            } else if (cst != null) {
                break;
            }
            size--;
        }

        if (size == 0) {
            return null;
        }

        // There is something worth encoding, so build up a result.

        CstArray.List list = new CstArray.List(size);
        for (int i = 0; i < size; i++) {
            EncodedField field = staticFields.get(i);
            Constant cst = staticValues.get(field);
            if (cst == null) {
                cst = Zeroes.zeroFor(field.getRef().getType());
            }
            list.set(i, cst);
        }
        list.setImmutable();

        return new CstArray(list);
    
protected voidplace0(Section addedTo, int offset)
{@inheritDoc}

        // Encode the data and note the size.

        ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();

        encodeOutput(addedTo.getFile(), out);
        encodedForm = out.toByteArray();
        setWriteSize(encodedForm.length);
    
public java.lang.StringtoHuman()
{@inheritDoc}

        return toString();
    
public voidwriteTo0(DexFile file, com.android.dx.util.AnnotatedOutput out)
{@inheritDoc}

        boolean annotates = out.annotates();

        if (annotates) {
            /*
             * The output is to be annotated, so redo the work previously
             * done by place0(), except this time annotations will actually
             * get emitted.
             */
            encodeOutput(file, out);
        } else {
            out.write(encodedForm);
        }