1be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver/*
2be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * Copyright 2012, Google Inc.
3be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * All rights reserved.
4be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *
5be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * Redistribution and use in source and binary forms, with or without
6be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * modification, are permitted provided that the following conditions are
7be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * met:
8be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *
9be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *     * Redistributions of source code must retain the above copyright
10be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * notice, this list of conditions and the following disclaimer.
11be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *     * Redistributions in binary form must reproduce the above
12be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * copyright notice, this list of conditions and the following disclaimer
13be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * in the documentation and/or other materials provided with the
14be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * distribution.
15be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *     * Neither the name of Google Inc. nor the names of its
16be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * contributors may be used to endorse or promote products derived from
17be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * this software without specific prior written permission.
18be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *
19be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver */
31be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
32be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruverpackage org.jf.dexlib2.dexbacked;
33be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
3422c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport com.google.common.collect.ImmutableSet;
350a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruverimport com.google.common.collect.Iterables;
36f81150ad43efac4d590f6b7ea1425896b7ffb011Ben Gruverimport org.jf.dexlib2.base.reference.BaseTypeReference;
37e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruverimport org.jf.dexlib2.dexbacked.raw.ClassDefItem;
3822c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
3922c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport org.jf.dexlib2.dexbacked.util.FixedSizeSet;
4022c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator;
410a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruverimport org.jf.dexlib2.dexbacked.util.VariableSizeLookaheadIterator;
42be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruverimport org.jf.dexlib2.iface.ClassDef;
430a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruverimport org.jf.dexlib2.iface.reference.FieldReference;
440a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruverimport org.jf.dexlib2.iface.reference.MethodReference;
450a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruverimport org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
460a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruverimport org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
47be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
48be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruverimport javax.annotation.Nonnull;
49be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruverimport javax.annotation.Nullable;
5012b970ed4dfad768002335503e49c348ea0ed69bBen Gruverimport java.util.Iterator;
5122c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruverimport java.util.Set;
52be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
53f81150ad43efac4d590f6b7ea1425896b7ffb011Ben Gruverpublic class DexBackedClassDef extends BaseTypeReference implements ClassDef {
5484c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver    @Nonnull public final DexBackedDexFile dexFile;
55d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    private final int classDefOffset;
56be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
570a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private final int staticFieldsOffset;
580a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private int instanceFieldsOffset = 0;
590a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private int directMethodsOffset = 0;
600a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private int virtualMethodsOffset = 0;
610a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
620a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private final int staticFieldCount;
630a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private final int instanceFieldCount;
640a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private final int directMethodCount;
650a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private final int virtualMethodCount;
66be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
67d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Nullable private AnnotationsDirectory annotationsDirectory;
68be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
6984c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver    public DexBackedClassDef(@Nonnull DexBackedDexFile dexFile,
70be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                             int classDefOffset) {
7184c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver        this.dexFile = dexFile;
72d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver        this.classDefOffset = classDefOffset;
730a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
74d8d16fd84428b0c420a7cc2e0f0862be3cbd0f47Ben Gruver        int classDataOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_DATA_OFFSET);
750a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (classDataOffset == 0) {
760a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            staticFieldsOffset = -1;
770a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            staticFieldCount = 0;
780a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            instanceFieldCount = 0;
790a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            directMethodCount = 0;
800a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            virtualMethodCount = 0;
810a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        } else {
820a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            DexReader reader = dexFile.readerAt(classDataOffset);
830a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            staticFieldCount = reader.readSmallUleb128();
840a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            instanceFieldCount = reader.readSmallUleb128();
850a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            directMethodCount = reader.readSmallUleb128();
860a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            virtualMethodCount = reader.readSmallUleb128();
870a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            staticFieldsOffset = reader.getOffset();
880a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        }
890a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
90d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    }
91be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
92d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Nonnull
93d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Override
94db389aa3a1d898d3a452f3f0b2220b334b23cb4cBen Gruver    public String getType() {
95e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        return dexFile.getType(dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_OFFSET));
96d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    }
97be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
98d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Nullable
99d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Override
100d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    public String getSuperclass() {
101e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        return dexFile.getOptionalType(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SUPERCLASS_OFFSET));
102be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
103be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
104d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Override
105d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    public int getAccessFlags() {
106e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        return dexFile.readSmallUint(classDefOffset + ClassDefItem.ACCESS_FLAGS_OFFSET);
107d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    }
108be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
109d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Nullable
110d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    @Override
111d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    public String getSourceFile() {
112e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        return dexFile.getOptionalString(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SOURCE_FILE_OFFSET));
113d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    }
114be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
115be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Nonnull
116be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Override
11722c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver    public Set<String> getInterfaces() {
118e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver        final int interfacesOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.INTERFACES_OFFSET);
119be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver        if (interfacesOffset > 0) {
12084c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver            final int size = dexFile.readSmallUint(interfacesOffset);
12122c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver            return new FixedSizeSet<String>() {
12225d385a441b95d56987c81f00f19297d799e1b31Ben Gruver                @Nonnull
123be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                @Override
124be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                public String readItem(int index) {
12584c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver                    return dexFile.getType(dexFile.readUshort(interfacesOffset + 4 + (2*index)));
126be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                }
127be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
128be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                @Override public int size() { return size; }
129be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver            };
130be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver        }
13122c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver        return ImmutableSet.of();
132be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
133be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
134be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Nonnull
135be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Override
13622c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver    public Set<? extends DexBackedAnnotation> getAnnotations() {
137d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver        return getAnnotationsDirectory().getClassAnnotations();
138be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
139be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
140be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Nonnull
141be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Override
1420a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    public Iterable<? extends DexBackedField> getStaticFields() {
1438979759556f31af324257fec9ebd47d3444cede0Ben Gruver        return getStaticFields(true);
1448979759556f31af324257fec9ebd47d3444cede0Ben Gruver    }
1458979759556f31af324257fec9ebd47d3444cede0Ben Gruver
1468979759556f31af324257fec9ebd47d3444cede0Ben Gruver    @Nonnull
1478979759556f31af324257fec9ebd47d3444cede0Ben Gruver    public Iterable<? extends DexBackedField> getStaticFields(final boolean skipDuplicates) {
1480a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (staticFieldCount > 0) {
1490a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            DexReader reader = dexFile.readerAt(staticFieldsOffset);
1500a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
1510a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory();
1520a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final int staticInitialValuesOffset =
1530a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    dexFile.readSmallUint(classDefOffset + ClassDefItem.STATIC_VALUES_OFFSET);
1540a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final int fieldsStartOffset = reader.getOffset();
1550a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
1560a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return new Iterable<DexBackedField>() {
1570a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Nonnull
1580a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Override
1590a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                public Iterator<DexBackedField> iterator() {
160902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                    final AnnotationsDirectory.AnnotationIterator annotationIterator =
161902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                            annotationsDirectory.getFieldAnnotationIterator();
162902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                    final StaticInitialValueIterator staticInitialValueIterator =
163902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                            StaticInitialValueIterator.newOrEmpty(dexFile, staticInitialValuesOffset);
164902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver
1650a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    return new VariableSizeLookaheadIterator<DexBackedField>(dexFile, fieldsStartOffset) {
1660a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int count;
1670a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable private FieldReference previousField;
1680a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int previousIndex;
1690a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
1700a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable
1710a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Override
1720a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        protected DexBackedField readNextItem(@Nonnull DexReader reader) {
1730a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                            while (true) {
1740a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                if (++count > staticFieldCount) {
1750a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    instanceFieldsOffset = reader.getOffset();
1760a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    return null;
17787179940cbe7b0570f2fbdd9bc0b218e3535bcf7Ben Gruver                                }
1780a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
179a8e05220c14778d93c97911044ff5124aadbd77cBen Gruver                                DexBackedField item = new DexBackedField(reader, DexBackedClassDef.this,
1800a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                        previousIndex, staticInitialValueIterator, annotationIterator);
1810a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                FieldReference currentField = previousField;
1820a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                FieldReference nextField = ImmutableFieldReference.of(item);
1830a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
1840a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousField = nextField;
1850a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousIndex = item.fieldIndex;
1860a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
1878979759556f31af324257fec9ebd47d3444cede0Ben Gruver                                if (skipDuplicates && currentField != null && currentField.equals(nextField)) {
1880a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    continue;
1890a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                }
1900a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
191be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                                return item;
192be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver                            }
1930a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        }
1940a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    };
1950a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                }
1960a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            };
1970a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        } else {
1980a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            instanceFieldsOffset = staticFieldsOffset;
1990a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return ImmutableSet.of();
2000a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        }
2010a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    }
202be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
2030a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Nonnull
2040a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Override
2050a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    public Iterable<? extends DexBackedField> getInstanceFields() {
2068979759556f31af324257fec9ebd47d3444cede0Ben Gruver        return getInstanceFields(true);
2078979759556f31af324257fec9ebd47d3444cede0Ben Gruver    }
2088979759556f31af324257fec9ebd47d3444cede0Ben Gruver
2098979759556f31af324257fec9ebd47d3444cede0Ben Gruver    @Nonnull
2108979759556f31af324257fec9ebd47d3444cede0Ben Gruver    public Iterable<? extends DexBackedField> getInstanceFields(final boolean skipDuplicates) {
2110a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (instanceFieldCount > 0) {
2120a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            DexReader reader = dexFile.readerAt(getInstanceFieldsOffset());
2130a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2140a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory();
2150a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final int fieldsStartOffset = reader.getOffset();
2160a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2170a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return new Iterable<DexBackedField>() {
2180a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Nonnull
2190a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Override
2200a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                public Iterator<DexBackedField> iterator() {
221902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                    final AnnotationsDirectory.AnnotationIterator annotationIterator =
222902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                            annotationsDirectory.getFieldAnnotationIterator();
223902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver
2240a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    return new VariableSizeLookaheadIterator<DexBackedField>(dexFile, fieldsStartOffset) {
2250a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int count;
2260a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable private FieldReference previousField;
2270a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int previousIndex;
2280a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2290a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable
2300a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Override
2310a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        protected DexBackedField readNextItem(@Nonnull DexReader reader) {
2320a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                            while (true) {
2330a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                if (++count > instanceFieldCount) {
2340a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    directMethodsOffset = reader.getOffset();
2350a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    return null;
2360a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                }
2370a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2380a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                DexBackedField item = new DexBackedField(reader, DexBackedClassDef.this,
2390a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                        previousIndex, annotationIterator);
2400a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                FieldReference currentField = previousField;
2410a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                FieldReference nextField = ImmutableFieldReference.of(item);
2420a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2430a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousField = nextField;
2440a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousIndex = item.fieldIndex;
2450a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2468979759556f31af324257fec9ebd47d3444cede0Ben Gruver                                if (skipDuplicates && currentField != null && currentField.equals(nextField)) {
2470a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    continue;
2480a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                }
2490a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2500a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                return item;
2510a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                            }
2520a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        }
2530a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    };
2540a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                }
2550a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            };
2560a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        } else {
2570a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            if (instanceFieldsOffset > 0) {
2580a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                directMethodsOffset = instanceFieldsOffset;
259be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver            }
2600a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return ImmutableSet.of();
261be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver        }
262be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
263be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
264be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Nonnull
265be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    @Override
2660a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    public Iterable<? extends DexBackedField> getFields() {
2670a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        return Iterables.concat(getStaticFields(), getInstanceFields());
2680a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    }
2690a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2700a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Nonnull
2710a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Override
2720a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    public Iterable<? extends DexBackedMethod> getDirectMethods() {
2738979759556f31af324257fec9ebd47d3444cede0Ben Gruver        return getDirectMethods(true);
2748979759556f31af324257fec9ebd47d3444cede0Ben Gruver    }
2758979759556f31af324257fec9ebd47d3444cede0Ben Gruver
2768979759556f31af324257fec9ebd47d3444cede0Ben Gruver    @Nonnull
2778979759556f31af324257fec9ebd47d3444cede0Ben Gruver    public Iterable<? extends DexBackedMethod> getDirectMethods(final boolean skipDuplicates) {
2780a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (directMethodCount > 0) {
2790a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            DexReader reader = dexFile.readerAt(getDirectMethodsOffset());
2800a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2810a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory();
2820a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final int methodsStartOffset = reader.getOffset();
2830a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2840a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return new Iterable<DexBackedMethod>() {
2850a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Nonnull
2860a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Override
2870a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                public Iterator<DexBackedMethod> iterator() {
288902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                    final AnnotationsDirectory.AnnotationIterator methodAnnotationIterator =
289902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                            annotationsDirectory.getMethodAnnotationIterator();
290902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                    final AnnotationsDirectory.AnnotationIterator parameterAnnotationIterator =
291902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                            annotationsDirectory.getParameterAnnotationIterator();
292902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver
2930a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    return new VariableSizeLookaheadIterator<DexBackedMethod>(dexFile, methodsStartOffset) {
2940a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int count;
2950a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable private MethodReference previousMethod;
2960a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int previousIndex;
2970a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
2980a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable
2990a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Override
3000a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        protected DexBackedMethod readNextItem(@Nonnull DexReader reader) {
3010a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                            while (true) {
3020a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                if (++count > directMethodCount) {
3030a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    virtualMethodsOffset = reader.getOffset();
3040a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    return null;
30587179940cbe7b0570f2fbdd9bc0b218e3535bcf7Ben Gruver                                }
3060a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
307269c15688bb2a6bc7331b114ef830d5558af8fa6Ben Gruver                                DexBackedMethod item = new DexBackedMethod(reader, DexBackedClassDef.this,
3080a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                        previousIndex, methodAnnotationIterator, parameterAnnotationIterator);
3090a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                MethodReference currentMethod = previousMethod;
3100a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                MethodReference nextMethod = ImmutableMethodReference.of(item);
3110a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3120a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousMethod = nextMethod;
3130a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousIndex = item.methodIndex;
3140a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3158979759556f31af324257fec9ebd47d3444cede0Ben Gruver                                if (skipDuplicates && currentMethod != null && currentMethod.equals(nextMethod)) {
3160a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    continue;
3170a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3180a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                }
31963d840670311d96aa92c38f1d118ab2d7f590ce3Ben Gruver                                return item;
32063d840670311d96aa92c38f1d118ab2d7f590ce3Ben Gruver                            }
3210a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        }
3220a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    };
3230a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                }
3240a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            };
3250a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        } else {
3260a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            if (directMethodsOffset > 0) {
3270a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                virtualMethodsOffset = directMethodsOffset;
32863d840670311d96aa92c38f1d118ab2d7f590ce3Ben Gruver            }
3290a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return ImmutableSet.of();
33063d840670311d96aa92c38f1d118ab2d7f590ce3Ben Gruver        }
331be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
332d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver
3330a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Nonnull
3348979759556f31af324257fec9ebd47d3444cede0Ben Gruver    public Iterable<? extends DexBackedMethod> getVirtualMethods(final boolean skipDuplicates) {
3350a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (virtualMethodCount > 0) {
3360a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            DexReader reader = dexFile.readerAt(getVirtualMethodsOffset());
3370a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3380a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory();
3390a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            final int methodsStartOffset = reader.getOffset();
3400a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3410a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return new Iterable<DexBackedMethod>() {
342902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                final AnnotationsDirectory.AnnotationIterator methodAnnotationIterator =
343902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                        annotationsDirectory.getMethodAnnotationIterator();
344902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                final AnnotationsDirectory.AnnotationIterator parameterAnnotationIterator =
345902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver                        annotationsDirectory.getParameterAnnotationIterator();
346902ba7d72d694c93ff48b21181bf94b58131bf05Ben Gruver
3470a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Nonnull
3480a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                @Override
3490a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                public Iterator<DexBackedMethod> iterator() {
3500a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    return new VariableSizeLookaheadIterator<DexBackedMethod>(dexFile, methodsStartOffset) {
3510a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int count;
3520a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable private MethodReference previousMethod;
3530a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        private int previousIndex;
3540a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3550a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Nullable
3560a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        @Override
3570a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        protected DexBackedMethod readNextItem(@Nonnull DexReader reader) {
3580a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                            while (true) {
3590a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                if (++count > virtualMethodCount) {
3600a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    return null;
3610a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                }
3620a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3630a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                DexBackedMethod item = new DexBackedMethod(reader, DexBackedClassDef.this,
3640a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                        previousIndex, methodAnnotationIterator, parameterAnnotationIterator);
3650a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                MethodReference currentMethod = previousMethod;
3660a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                MethodReference nextMethod = ImmutableMethodReference.of(item);
3670a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3680a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousMethod = nextMethod;
3690a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                previousIndex = item.methodIndex;
3700a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3718979759556f31af324257fec9ebd47d3444cede0Ben Gruver                                if (skipDuplicates && currentMethod != null && currentMethod.equals(nextMethod)) {
3720a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                    continue;
3730a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                }
3740a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                                return item;
3750a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                            }
3760a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                        }
3770a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                    };
3780a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver                }
3790a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            };
3800a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        } else {
3810a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return ImmutableSet.of();
382d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver        }
3830a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    }
3840a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
3850a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Nonnull
3860a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    @Override
3878979759556f31af324257fec9ebd47d3444cede0Ben Gruver    public Iterable<? extends DexBackedMethod> getVirtualMethods() {
3888979759556f31af324257fec9ebd47d3444cede0Ben Gruver        return getVirtualMethods(true);
3898979759556f31af324257fec9ebd47d3444cede0Ben Gruver    }
3908979759556f31af324257fec9ebd47d3444cede0Ben Gruver
3918979759556f31af324257fec9ebd47d3444cede0Ben Gruver    @Nonnull
3928979759556f31af324257fec9ebd47d3444cede0Ben Gruver    @Override
3930a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    public Iterable<? extends DexBackedMethod> getMethods() {
3940a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        return Iterables.concat(getDirectMethods(), getVirtualMethods());
395d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    }
396d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver
397d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    private AnnotationsDirectory getAnnotationsDirectory() {
398d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver        if (annotationsDirectory == null) {
399e8158c86efe5494fb5b369e096c7a857623a1b11Ben Gruver            int annotationsDirectoryOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.ANNOTATIONS_OFFSET);
40084c1762a62d7fc6638432c6c56e0422aa8cc6939Ben Gruver            annotationsDirectory = AnnotationsDirectory.newOrEmpty(dexFile, annotationsDirectoryOffset);
401d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver        }
402d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver        return annotationsDirectory;
403d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver    }
4040a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
4050a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private int getInstanceFieldsOffset() {
4060a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (instanceFieldsOffset > 0) {
4070a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return instanceFieldsOffset;
4080a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        }
4090a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        DexReader reader = new DexReader(dexFile, staticFieldsOffset);
410f939e912b53bccab66013c694442fa2f40d970e1Ben Gruver        DexBackedField.skipFields(reader, staticFieldCount);
4110a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        instanceFieldsOffset = reader.getOffset();
4120a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        return instanceFieldsOffset;
4130a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    }
4140a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
4150a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private int getDirectMethodsOffset() {
4160a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (directMethodsOffset > 0) {
4170a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return directMethodsOffset;
4180a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        }
4190a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        DexReader reader = dexFile.readerAt(getInstanceFieldsOffset());
420f939e912b53bccab66013c694442fa2f40d970e1Ben Gruver        DexBackedField.skipFields(reader, instanceFieldCount);
4210a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        directMethodsOffset = reader.getOffset();
4220a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        return directMethodsOffset;
4230a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    }
4240a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver
4250a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    private int getVirtualMethodsOffset() {
4260a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        if (virtualMethodsOffset > 0) {
4270a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver            return virtualMethodsOffset;
4280a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        }
4290a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        DexReader reader = dexFile.readerAt(getDirectMethodsOffset());
430f939e912b53bccab66013c694442fa2f40d970e1Ben Gruver        DexBackedMethod.skipMethods(reader, directMethodCount);
4310a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        virtualMethodsOffset = reader.getOffset();
4320a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver        return virtualMethodsOffset;
4330a18ea7f8b62e51945a79ac37802133a24c9a742Ben Gruver    }
434be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver}
435