com.android.dex.Dex Java Examples

The following examples show how to use com.android.dex.Dex. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Main.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Merges the dex files in library jars. If multiple dex files define the
 * same type, this fails with an exception.
 */
private byte[] mergeLibraryDexBuffers(byte[] outArray) throws IOException {
    ArrayList<Dex> dexes = new ArrayList<Dex>();
    if (outArray != null) {
        dexes.add(new Dex(outArray));
    }
    for (byte[] libraryDex : libraryDexBuffers) {
        dexes.add(new Dex(libraryDex));
    }
    if (dexes.isEmpty()) {
        return null;
    }
    DexMerger dexMerger = new DexMerger(
        dexes.toArray(new Dex[0]),
        CollisionPolicy.FAIL,
        context);
    Dex merged = dexMerger.merge();
    return merged.getBytes();
}
 
Example #2
Source File: MergeTest.java    From buck with Apache License 2.0 6 votes vote down vote up
public static void main(String[] args) throws Throwable {

    for (int i = 0; i < NUMBER_OF_TRIES; i++) {
      String fileName1 = args[(int) (Math.random() * args.length)];
      String fileName2 = args[(int) (Math.random() * args.length)];
      try {
        Dex toMerge = new Dex(new File(fileName1));
        Dex toMerge2 = new Dex(new File(fileName2));
        new DexMerger(toMerge, toMerge2, CollisionPolicy.KEEP_FIRST).merge();
      } catch (DexIndexOverflowException e) {
        // ignore index overflow
      } catch (Throwable t) {
        System.err.println(
            "Problem merging those 2 dexes: \"" + fileName1 + "\" and \"" + fileName2 + "\"");
        throw t;
      }
    }
  }
 
Example #3
Source File: BaseAndroidClassLoader.java    From rhino-android with Apache License 2.0 6 votes vote down vote up
/**
 * {@inheritDoc}
 */
@Override
public Class<?> defineClass(String name, byte[] data) {
    try {
        DexOptions dexOptions = new DexOptions();
        DexFile dexFile = new DexFile(dexOptions);
        DirectClassFile classFile = new DirectClassFile(data, name.replace('.', '/') + ".class", true);
        classFile.setAttributeFactory(StdAttributeFactory.THE_ONE);
        classFile.getMagic();
        DxContext context = new DxContext();
        dexFile.add(CfTranslator.translate(context, classFile, null, new CfOptions(), dexOptions, dexFile));
        Dex dex = new Dex(dexFile.toDex(null, false));
        Dex oldDex = getLastDex();
        if (oldDex != null) {
            dex = new DexMerger(new Dex[]{dex, oldDex}, CollisionPolicy.KEEP_FIRST, context).merge();
        }
        return loadClass(dex, name);
    } catch (IOException | ClassNotFoundException e) {
        throw new FatalLoadingException(e);
    }
}
 
Example #4
Source File: ClassNode.java    From Box with Apache License 2.0 6 votes vote down vote up
private void loadStaticValues(ClassDef cls, List<FieldNode> staticFields) throws DecodeException {
	for (FieldNode f : staticFields) {
		if (f.getAccessFlags().isFinal()) {
			f.addAttr(FieldInitAttr.NULL_VALUE);
		}
	}
	int offset = cls.getStaticValuesOffset();
	if (offset == 0) {
		return;
	}
	Dex.Section section = dex.openSection(offset);
	StaticValuesParser parser = new StaticValuesParser(dex, section);
	parser.processFields(staticFields);

	// process const fields
	root().getConstValues().processConstFields(this, staticFields);
}
 
Example #5
Source File: DexMerger.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Reads a class_def_item beginning at {@code in} and writes the index and
 * data.
 */
private void transformClassDef(Dex in, ClassDef classDef, IndexMap indexMap) {
    idsDefsOut.assertFourByteAligned();
    idsDefsOut.writeInt(classDef.getTypeIndex());
    idsDefsOut.writeInt(classDef.getAccessFlags());
    idsDefsOut.writeInt(classDef.getSupertypeIndex());
    idsDefsOut.writeInt(classDef.getInterfacesOffset());

    int sourceFileIndex = indexMap.adjustString(classDef.getSourceFileIndex());
    idsDefsOut.writeInt(sourceFileIndex);

    int annotationsOff = classDef.getAnnotationsOffset();
    idsDefsOut.writeInt(indexMap.adjustAnnotationDirectory(annotationsOff));

    int classDataOff = classDef.getClassDataOffset();
    if (classDataOff == 0) {
        idsDefsOut.writeInt(0);
    } else {
        idsDefsOut.writeInt(classDataOut.getPosition());
        ClassData classData = in.readClassData(classDef);
        transformClassData(in, classData, indexMap);
    }

    int staticValuesOff = classDef.getStaticValuesOffset();
    idsDefsOut.writeInt(indexMap.adjustEncodedArray(staticValuesOff));
}
 
Example #6
Source File: DexMerger.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Reads a class_def_item beginning at {@code in} and writes the index and
 * data.
 */
private void transformClassDef(Dex in, ClassDef classDef, IndexMap indexMap) {
    idsDefsOut.assertFourByteAligned();
    idsDefsOut.writeInt(classDef.getTypeIndex());
    idsDefsOut.writeInt(classDef.getAccessFlags());
    idsDefsOut.writeInt(classDef.getSupertypeIndex());
    idsDefsOut.writeInt(classDef.getInterfacesOffset());

    int sourceFileIndex = indexMap.adjustString(classDef.getSourceFileIndex());
    idsDefsOut.writeInt(sourceFileIndex);

    int annotationsOff = classDef.getAnnotationsOffset();
    idsDefsOut.writeInt(indexMap.adjustAnnotationDirectory(annotationsOff));

    int classDataOff = classDef.getClassDataOffset();
    if (classDataOff == 0) {
        idsDefsOut.writeInt(0);
    } else {
        idsDefsOut.writeInt(classDataOut.getPosition());
        ClassData classData = in.readClassData(classDef);
        transformClassData(in, classData, indexMap);
    }

    int staticValuesOff = classDef.getStaticValuesOffset();
    idsDefsOut.writeInt(indexMap.adjustStaticValues(staticValuesOff));
}
 
Example #7
Source File: DexFileAggregatorTest.java    From bazel with Apache License 2.0 6 votes vote down vote up
@Test
public void testMonodex_alwaysWritesSingleShard() throws Exception {
  DexFileAggregator dexer =
      new DexFileAggregator(
          new DxContext(),
          dest,
          newDirectExecutorService(),
          MultidexStrategy.OFF,
          /*forceJumbo=*/ false,
          2 /* dex has more than 2 methods and fields */,
          WASTE,
          DexFileMergerTest.DEX_PREFIX);
  Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
  dexer.add(dex);
  dexer.add(dex2);
  verify(dest, times(0)).addFile(any(ZipEntry.class), any(Dex.class));
  dexer.close();
  verify(dest).addFile(any(ZipEntry.class), written.capture());
  assertThat(Iterables.size(written.getValue().classDefs())).isEqualTo(2);
}
 
Example #8
Source File: DexMergeTest.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Merging dex files uses pessimistic sizes that naturally leave gaps in the
 * output files. If those gaps grow too large, the merger is supposed to
 * compact the result. This exercises that by repeatedly merging a dex with
 * itself.
 */
public void testMergedOutputSizeIsBounded() throws Exception {
    /*
     * At the time this test was written, the output would grow ~25% with
     * each merge. Setting a low 1KiB ceiling on the maximum size caused
     * the file to be compacted every four merges.
     */
    int steps = 100;
    int compactWasteThreshold = 1024;

    Dex dexA = resourceToDexBuffer("/testdata/Basic.dex");
    Dex dexB = resourceToDexBuffer("/testdata/TryCatchFinally.dex");
    Dex merged = new DexMerger(dexA, dexB, CollisionPolicy.KEEP_FIRST).merge();

    int maxLength = 0;
    for (int i = 0; i < steps; i++) {
        DexMerger dexMerger = new DexMerger(dexA, merged, CollisionPolicy.KEEP_FIRST);
        dexMerger.setCompactWasteThreshold(compactWasteThreshold);
        merged = dexMerger.merge();
        maxLength = Math.max(maxLength, merged.getLength());
    }

    int maxExpectedLength = dexA.getLength() + dexB.getLength() + compactWasteThreshold;
    assertTrue(maxLength + " < " + maxExpectedLength, maxLength < maxExpectedLength);
}
 
Example #9
Source File: DexMerger.java    From Box with Apache License 2.0 6 votes vote down vote up
private void transformClassData(Dex in, ClassData classData, IndexMap indexMap) {
    contentsOut.classDatas.size++;

    ClassData.Field[] staticFields = classData.getStaticFields();
    ClassData.Field[] instanceFields = classData.getInstanceFields();
    ClassData.Method[] directMethods = classData.getDirectMethods();
    ClassData.Method[] virtualMethods = classData.getVirtualMethods();

    classDataOut.writeUleb128(staticFields.length);
    classDataOut.writeUleb128(instanceFields.length);
    classDataOut.writeUleb128(directMethods.length);
    classDataOut.writeUleb128(virtualMethods.length);

    transformFields(indexMap, staticFields);
    transformFields(indexMap, instanceFields);
    transformMethods(in, indexMap, directMethods);
    transformMethods(in, indexMap, virtualMethods);
}
 
Example #10
Source File: DexMerger.java    From buck with Apache License 2.0 6 votes vote down vote up
private void transformMethods(Dex in, IndexMap indexMap, ClassData.Method[] methods) {
    int lastOutMethodIndex = 0;
    for (ClassData.Method method : methods) {
        int outMethodIndex = indexMap.adjustMethod(method.getMethodIndex());
        classDataOut.writeUleb128(outMethodIndex - lastOutMethodIndex);
        lastOutMethodIndex = outMethodIndex;

        classDataOut.writeUleb128(method.getAccessFlags());

        if (method.getCodeOffset() == 0) {
            classDataOut.writeUleb128(0);
        } else {
            codeOut.alignToFourBytesWithZeroFill();
            classDataOut.writeUleb128(codeOut.getPosition());
            transformCode(in, in.readCode(method), indexMap);
        }
    }
}
 
Example #11
Source File: FindUsages.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the set of types that can be assigned to {@code typeIndex}.
 */
private Set<Integer> findAssignableTypes(Dex dex, int typeIndex) {
    Set<Integer> assignableTypes = new HashSet<Integer>();
    assignableTypes.add(typeIndex);

    for (ClassDef classDef : dex.classDefs()) {
        if (assignableTypes.contains(classDef.getSupertypeIndex())) {
            assignableTypes.add(classDef.getTypeIndex());
            continue;
        }

        for (int implemented : classDef.getInterfaces()) {
            if (assignableTypes.contains(implemented)) {
                assignableTypes.add(classDef.getTypeIndex());
                break;
            }
        }
    }

    return assignableTypes;
}
 
Example #12
Source File: DexMerger.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Transform all annotation set ref lists.
 */
private void transformAnnotationSetRefList(IndexMap indexMap, Dex.Section refListIn) {
    contentsOut.annotationSetRefLists.size++;
    annotationSetRefListOut.assertFourByteAligned();
    indexMap.putAnnotationSetRefListOffset(
            refListIn.getPosition(), annotationSetRefListOut.getPosition());

    int parameterCount = refListIn.readInt();
    annotationSetRefListOut.writeInt(parameterCount);
    for (int p = 0; p < parameterCount; p++) {
        annotationSetRefListOut.writeInt(indexMap.adjustAnnotationSet(refListIn.readInt()));
    }
}
 
Example #13
Source File: DexMerger.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Compute sizes for merging several dexes.
 */
public WriterSizes(Dex[] dexes) {
    for (int i = 0; i < dexes.length; i++) {
        plus(dexes[i], false);
    }
    fourByteAlign();
}
 
Example #14
Source File: DexBuilderTest.java    From bazel with Apache License 2.0 5 votes vote down vote up
@Test
public void testBuildDexArchive() throws Exception {
  DexBuilder.Options options = new DexBuilder.Options();
  // Use Jar file that has this test in it as the input Jar
  Runfiles runfiles = Runfiles.create();
  options.inputJar = Paths.get(runfiles.rlocation(System.getProperty("testinputjar")));
  options.outputZip =
      FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR"), "dex_builder_test.zip");
  options.maxThreads = 1;
  Dexing.DexingOptions dexingOptions = new Dexing.DexingOptions();
  dexingOptions.optimize = true;
  dexingOptions.positionInfo = PositionList.LINES;
  DexBuilder.buildDexArchive(options, new Dexing(dexingOptions));
  assertThat(options.outputZip.toFile().exists()).isTrue();

  HashSet<String> files = new HashSet<>();
  try (ZipFile zip = new ZipFile(options.outputZip.toFile())) {
    Enumeration<? extends ZipEntry> entries = zip.entries();
    while (entries.hasMoreElements()) {
      ZipEntry entry = entries.nextElement();
      files.add(entry.getName());
      if (entry.getName().endsWith(".dex")) {
        Dex dex = new Dex(zip.getInputStream(entry));
        assertWithMessage(entry.getName()).that(dex.classDefs()).hasSize(1);
      } else if (entry.getName().endsWith("/testresource.txt")) {
        byte[] content = ByteStreams.toByteArray(zip.getInputStream(entry));
        assertWithMessage(entry.getName()).that(content).isEqualTo("test".getBytes(UTF_8));
      }
    }
  }
  // Make sure this test is in the Zip file, which also means we parsed its dex code above
  assertThat(files).contains(getClass().getName().replace('.', '/') + ".class.dex");
  // Make sure test resource is in the Zip file, which also means it had the expected content
  assertThat(files)
      .contains(getClass().getPackage().getName().replace('.', '/') + "/testresource.txt");
}
 
Example #15
Source File: FindUsages.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the methods with {@code memberNameIndex} declared by {@code
 * declaringType} and its subtypes.
 */
private Set<Integer> getMethodIds(Dex dex, Set<Integer> memberNameIndexes, int declaringType) {
    Set<Integer> subtypes = findAssignableTypes(dex, declaringType);

    Set<Integer> methods = new HashSet<Integer>();
    int methodIndex = 0;
    for (MethodId method : dex.methodIds()) {
        if (memberNameIndexes.contains(method.getNameIndex())
                && subtypes.contains(method.getDeclaringClassIndex())) {
            methods.add(methodIndex);
        }
        methodIndex++;
    }
    return methods;
}
 
Example #16
Source File: DexMerger.java    From buck with Apache License 2.0 5 votes vote down vote up
private int readIntoMap(Dex.Section in, TableOfContents.Section section, IndexMap indexMap,
                        int index, TreeMap<T, List<Integer>> values, int dex) {
    int offset = in != null ? in.getPosition() : -1;
    if (index < section.size) {
        T v = read(in, indexMap, index);
        List<Integer> l = values.get(v);
        if (l == null) {
            l = new ArrayList<Integer>();
            values.put(v, l);
        }
        l.add(new Integer(dex));
    }
    return offset;
}
 
Example #17
Source File: DexMerger.java    From Box with Apache License 2.0 5 votes vote down vote up
private int readIntoMap(Dex.Section in, TableOfContents.Section section, IndexMap indexMap,
                        int index, TreeMap<T, List<Integer>> values, int dex) {
    int offset = in != null ? in.getPosition() : -1;
    if (index < section.size) {
        T v = read(in, indexMap, index);
        List<Integer> l = values.get(v);
        if (l == null) {
            l = new ArrayList<Integer>();
            values.put(v, l);
        }
        l.add(dex);
    }
    return offset;
}
 
Example #18
Source File: DexFileAggregator.java    From bazel with Apache License 2.0 5 votes vote down vote up
@Override
public Dex call() throws IOException {
  try {
    return merge(dexes);
  } catch (Throwable t) {
    // Print out exceptions so they don't get swallowed completely
    t.printStackTrace();
    Throwables.throwIfInstanceOf(t, IOException.class);
    Throwables.throwIfUnchecked(t);
    throw new AssertionError(t);  // shouldn't get here
  }
}
 
Example #19
Source File: FindUsages.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the fields with {@code memberNameIndex} declared by {@code
 * declaringType}.
 */
private Set<Integer> getFieldIds(Dex dex, Set<Integer> memberNameIndexes, int declaringType) {
    Set<Integer> fields = new HashSet<Integer>();
    int fieldIndex = 0;
    for (FieldId fieldId : dex.fieldIds()) {
        if (memberNameIndexes.contains(fieldId.getNameIndex())
                && declaringType == fieldId.getDeclaringClassIndex()) {
            fields.add(fieldIndex);
        }
        fieldIndex++;
    }
    return fields;
}
 
Example #20
Source File: DexMerger.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Reads just enough data on each class so that we can sort it and then find
 * it later.
 */
private void readSortableTypes(SortableType[] sortableTypes, Dex buffer,
        IndexMap indexMap) {
    for (ClassDef classDef : buffer.classDefs()) {
        SortableType sortableType = indexMap.adjust(
                new SortableType(buffer, indexMap, classDef));
        int t = sortableType.getTypeIndex();
        if (sortableTypes[t] == null) {
            sortableTypes[t] = sortableType;
        } else if (collisionPolicy != CollisionPolicy.KEEP_FIRST) {
            throw new DexException("Multiple dex files define "
                    + buffer.typeNames().get(classDef.getTypeIndex()));
        }
    }
}
 
Example #21
Source File: FindUsages.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the fields with {@code memberNameIndex} declared by {@code
 * declaringType}.
 */
private Set<Integer> getFieldIds(Dex dex, Set<Integer> memberNameIndexes, int declaringType) {
    Set<Integer> fields = new HashSet<Integer>();
    int fieldIndex = 0;
    for (FieldId fieldId : dex.fieldIds()) {
        if (memberNameIndexes.contains(fieldId.getNameIndex())
                && declaringType == fieldId.getDeclaringClassIndex()) {
            fields.add(fieldIndex);
        }
        fieldIndex++;
    }
    return fields;
}
 
Example #22
Source File: Main.java    From Box with Apache License 2.0 5 votes vote down vote up
public static void main(String[] args) throws IOException {
    String dexFile = args[0];
    String pattern = args[1];

    Dex dex = new Dex(new File(dexFile));
    int count = new Grep(dex, Pattern.compile(pattern), new PrintWriter(System.out)).grep();
    System.exit((count > 0) ? 0 : 1);
}
 
Example #23
Source File: DexFileMergerTest.java    From bazel with Apache License 2.0 5 votes vote down vote up
private void assertSingleDexOutput(int expectedClassCount, Path outputArchive, String dexFileName)
    throws IOException {
  try (ZipFile output = new ZipFile(outputArchive.toFile())) {
    ZipEntry entry = Iterators.getOnlyElement(Iterators.forEnumeration(output.entries()));
    assertThat(entry.getName()).isEqualTo(dexFileName);
    Dex dex = new Dex(output.getInputStream(entry));
    assertThat(dex.classDefs()).hasSize(expectedClassCount);
  }
}
 
Example #24
Source File: DexMerger.java    From Box with Apache License 2.0 5 votes vote down vote up
private void transformStaticValues(Dex in, IndexMap indexMap) {
    TableOfContents.Section section = in.getTableOfContents().encodedArrays;
    if (section.exists()) {
        Dex.Section staticValuesIn = in.open(section.off);
        for (int i = 0; i < section.size; i++) {
            transformStaticValues(staticValuesIn, indexMap);
        }
    }
}
 
Example #25
Source File: FindUsages.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the methods with {@code memberNameIndex} declared by {@code
 * declaringType} and its subtypes.
 */
private Set<Integer> getMethodIds(Dex dex, Set<Integer> memberNameIndexes, int declaringType) {
    Set<Integer> subtypes = findAssignableTypes(dex, declaringType);

    Set<Integer> methods = new HashSet<Integer>();
    int methodIndex = 0;
    for (MethodId method : dex.methodIds()) {
        if (memberNameIndexes.contains(method.getNameIndex())
                && subtypes.contains(method.getDeclaringClassIndex())) {
            methods.add(methodIndex);
        }
        methodIndex++;
    }
    return methods;
}
 
Example #26
Source File: Main.java    From Box with Apache License 2.0 5 votes vote down vote up
public static void main(String[] args) throws IOException {
    String dexFile = args[0];
    String declaredBy = args[1];
    String memberName = args[2];

    Dex dex = new Dex(new File(dexFile));
    PrintWriter out = new PrintWriter(System.out);
    new FindUsages(dex, declaredBy, memberName, out).findUsages();
    out.flush();
}
 
Example #27
Source File: FindUsages.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the methods with {@code memberNameIndex} declared by {@code
 * declaringType} and its subtypes.
 */
private Set<Integer> getMethodIds(Dex dex, Set<Integer> memberNameIndexes, int declaringType) {
    Set<Integer> subtypes = findAssignableTypes(dex, declaringType);

    Set<Integer> methods = new HashSet<Integer>();
    int methodIndex = 0;
    for (MethodId method : dex.methodIds()) {
        if (memberNameIndexes.contains(method.getNameIndex())
                && subtypes.contains(method.getDeclaringClassIndex())) {
            methods.add(methodIndex);
        }
        methodIndex++;
    }
    return methods;
}
 
Example #28
Source File: FindUsages.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the fields with {@code memberNameIndex} declared by {@code
 * declaringType}.
 */
private Set<Integer> getFieldIds(Dex dex, Set<Integer> memberNameIndexes, int declaringType) {
    Set<Integer> fields = new HashSet<Integer>();
    int fieldIndex = 0;
    for (FieldId fieldId : dex.fieldIds()) {
        if (memberNameIndexes.contains(fieldId.getNameIndex())
                && declaringType == fieldId.getDeclaringClassIndex()) {
            fields.add(fieldIndex);
        }
        fieldIndex++;
    }
    return fields;
}
 
Example #29
Source File: DexFileAggregatorTest.java    From bazel with Apache License 2.0 5 votes vote down vote up
@Test
public void testClose_emptyWritesNothing() throws Exception {
  DexFileAggregator dexer =
      new DexFileAggregator(
          new DxContext(),
          dest,
          newDirectExecutorService(),
          MultidexStrategy.MINIMAL,
          /*forceJumbo=*/ false,
          DEX_LIMIT,
          WASTE,
          DexFileMergerTest.DEX_PREFIX);
  dexer.close();
  verify(dest, times(0)).addFile(any(ZipEntry.class), any(Dex.class));
}
 
Example #30
Source File: Main.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Merges the dex files in library jars. If multiple dex files define the
 * same type, this fails with an exception.
 */
private byte[] mergeLibraryDexBuffers(byte[] outArray) throws IOException {
    ArrayList<Dex> dexes = new ArrayList<Dex>();
    if (outArray != null) {
        dexes.add(new Dex(outArray));
    }
    for (byte[] libraryDex : libraryDexBuffers) {
        dexes.add(new Dex(libraryDex));
    }
    if (dexes.isEmpty()) {
        return null;
    }
    Dex merged = new DexMerger(dexes.toArray(new Dex[dexes.size()]), CollisionPolicy.FAIL, context).merge();
    return merged.getBytes();
}