FileDocCategorySizeDatePackage
ClassDataItem.javaAPI DocAndroid 1.5 API13715Wed May 06 22:41:02 BST 2009com.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 dex file, as opposed to a random-access form.

Fields Summary
private final com.android.dx.rop.cst.CstType
thisClass
non-null; what class this data is for, just for listing generation
private final ArrayList
staticFields
non-null; list of static fields
private final HashMap
staticValues
non-null; list of initial values for static fields
private final ArrayList
instanceFields
non-null; list of instance fields
private final ArrayList
directMethods
non-null; list of direct methods
private final ArrayList
virtualMethods
non-null; list of virtual methods
private com.android.dx.rop.cst.CstArray
staticValuesConstant
null-ok; static initializer list; set in {@link #addContents}
private byte[]
encodedForm
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 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 (static and/or private) method.

param
method 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 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 non-null; the field to add
param
value 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 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 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 non-null; file this instance is part of
param
out non-null; where to write to
param
label non-null; the label for the purposes of annotation
param
list 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 non-null; file this instance is part of
param
out non-null; where to write to

        boolean annotates = out.annotates();
        int svSize = (staticValuesConstant == null) ? 0 :
            staticValuesConstant.getList().size();

        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 non-null; file this instance is part of
param
out non-null; where to write to
param
label non-null; the label for the purposes of annotation
param
size >= 0; the size to write

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

        out.writeUnsignedLeb128(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
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-null values.

return
null-ok; the corresponding constant or 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
true if this instance is empty or 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-null values.

return
null-ok; the corresponding constant or 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);
        }