OSDN Git Service

Switch Dex from byte[] to ByteBuffer for backing store. Part 2.
authorJesse Wilson <jessewilson@google.com>
Mon, 19 Sep 2011 02:45:39 +0000 (22:45 -0400)
committerBrian Carlstrom <bdc@google.com>
Tue, 30 Apr 2013 17:53:46 +0000 (10:53 -0700)
Change-Id: Ifd3672027d075b6c9f8df208a04bc33122c883af
(cherry picked from commit f8357511efd16d76ce4410459c15dbb08b0140b6)

Conflicts:
dx/src/com/android/dx/merge/DexMerger.java

dx/src/com/android/dx/io/DexHasher.java [deleted file]
dx/src/com/android/dx/merge/DexMerger.java

diff --git a/dx/src/com/android/dx/io/DexHasher.java b/dx/src/com/android/dx/io/DexHasher.java
deleted file mode 100644 (file)
index 4259259..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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 com.android.dx.io;
-
-import com.android.dex.Dex;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.zip.Adler32;
-
-/**
- * Generates and stores the checksum and signature of a dex file.
- */
-public final class DexHasher {
-    private static final int CHECKSUM_OFFSET = 8;
-    private static final int CHECKSUM_SIZE = 4;
-    private static final int SIGNATURE_OFFSET = CHECKSUM_OFFSET + CHECKSUM_SIZE;
-    private static final int SIGNATURE_SIZE = 20;
-
-    /**
-     * Returns the signature of all but the first 32 bytes of {@code dex}. The
-     * first 32 bytes of dex files are not specified to be included in the
-     * signature.
-     */
-    public byte[] computeSignature(Dex dex) throws IOException {
-        MessageDigest digest;
-        try {
-            digest = MessageDigest.getInstance("SHA-1");
-        } catch (NoSuchAlgorithmException e) {
-            throw new AssertionError();
-        }
-        int offset = SIGNATURE_OFFSET + SIGNATURE_SIZE;
-
-        byte[] bytes = dex.getBytes();
-        digest.update(bytes, offset, bytes.length - offset);
-        return digest.digest();
-    }
-
-    /**
-     * Returns the checksum of all but the first 12 bytes of {@code dex}.
-     */
-    public int computeChecksum(Dex dex) throws IOException {
-        Adler32 adler32 = new Adler32();
-        int offset = CHECKSUM_OFFSET + CHECKSUM_SIZE;
-
-        byte[] bytes = dex.getBytes();
-        adler32.update(bytes, offset, bytes.length - offset);
-        return (int) adler32.getValue();
-    }
-
-    /**
-     * Generates the signature and checksum of the dex file {@code out} and
-     * writes them to the file.
-     */
-    public void writeHashes(Dex dex) throws IOException {
-        byte[] signature = computeSignature(dex);
-        dex.open(SIGNATURE_OFFSET).write(signature);
-
-        int checksum = computeChecksum(dex);
-        dex.open(CHECKSUM_OFFSET).writeInt(checksum);
-    }
-}
index 329920e..0a92e48 100644 (file)
@@ -28,7 +28,6 @@ import com.android.dex.ProtoId;
 import com.android.dex.SizeOf;
 import com.android.dex.TableOfContents;
 import com.android.dex.TypeList;
-import com.android.dx.io.DexHasher;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -45,7 +44,7 @@ public final class DexMerger {
     private final CollisionPolicy collisionPolicy;
     private final WriterSizes writerSizes;
 
-    private final Dex dexOut = new Dex();
+    private final Dex dexOut;
 
     private final Dex.Section headerOut;
 
@@ -100,6 +99,8 @@ public final class DexMerger {
         this.collisionPolicy = collisionPolicy;
         this.writerSizes = writerSizes;
 
+        dexOut = new Dex(writerSizes.size());
+
         TableOfContents aContents = dexA.getTableOfContents();
         TableOfContents bContents = dexB.getTableOfContents();
         aIndexMap = new IndexMap(dexOut, aContents);
@@ -111,46 +112,45 @@ public final class DexMerger {
         idsDefsOut = dexOut.appendSection(writerSizes.idsDefs, "ids defs");
 
         contentsOut = dexOut.getTableOfContents();
-        contentsOut.dataOff = dexOut.getLength();
+        contentsOut.dataOff = dexOut.getNextSectionStart();
 
-        contentsOut.mapList.off = dexOut.getLength();
+        contentsOut.mapList.off = dexOut.getNextSectionStart();
         contentsOut.mapList.size = 1;
         mapListOut = dexOut.appendSection(writerSizes.mapList, "map list");
 
-        contentsOut.typeLists.off = dexOut.getLength();
+        contentsOut.typeLists.off = dexOut.getNextSectionStart();
         typeListOut = dexOut.appendSection(writerSizes.typeList, "type list");
 
-        contentsOut.annotationSetRefLists.off = dexOut.getLength();
+        contentsOut.annotationSetRefLists.off = dexOut.getNextSectionStart();
         annotationSetRefListOut = dexOut.appendSection(
                 writerSizes.annotationsSetRefList, "annotation set ref list");
 
-        contentsOut.annotationSets.off = dexOut.getLength();
+        contentsOut.annotationSets.off = dexOut.getNextSectionStart();
         annotationSetOut = dexOut.appendSection(writerSizes.annotationsSet, "annotation sets");
 
-        contentsOut.classDatas.off = dexOut.getLength();
+        contentsOut.classDatas.off = dexOut.getNextSectionStart();
         classDataOut = dexOut.appendSection(writerSizes.classData, "class data");
 
-        contentsOut.codes.off = dexOut.getLength();
+        contentsOut.codes.off = dexOut.getNextSectionStart();
         codeOut = dexOut.appendSection(writerSizes.code, "code");
 
-        contentsOut.stringDatas.off = dexOut.getLength();
+        contentsOut.stringDatas.off = dexOut.getNextSectionStart();
         stringDataOut = dexOut.appendSection(writerSizes.stringData, "string data");
 
-        contentsOut.debugInfos.off = dexOut.getLength();
+        contentsOut.debugInfos.off = dexOut.getNextSectionStart();
         debugInfoOut = dexOut.appendSection(writerSizes.debugInfo, "debug info");
 
-        contentsOut.annotations.off = dexOut.getLength();
+        contentsOut.annotations.off = dexOut.getNextSectionStart();
         annotationOut = dexOut.appendSection(writerSizes.annotation, "annotation");
 
-        contentsOut.encodedArrays.off = dexOut.getLength();
+        contentsOut.encodedArrays.off = dexOut.getNextSectionStart();
         encodedArrayOut = dexOut.appendSection(writerSizes.encodedArray, "encoded array");
 
-        contentsOut.annotationsDirectories.off = dexOut.getLength();
+        contentsOut.annotationsDirectories.off = dexOut.getNextSectionStart();
         annotationsDirectoryOut = dexOut.appendSection(
                 writerSizes.annotationsDirectory, "annotations directory");
 
-        dexOut.noMoreSections();
-        contentsOut.dataSize = dexOut.getLength() - contentsOut.dataOff;
+        contentsOut.dataSize = dexOut.getNextSectionStart() - contentsOut.dataOff;
     }
 
     public void setCompactWasteThreshold(int compactWasteThreshold) {
@@ -177,7 +177,7 @@ public final class DexMerger {
         contentsOut.writeMap(mapListOut);
 
         // generate and write the hashes
-        new DexHasher().writeHashes(dexOut);
+        dexOut.writeHashes();
 
         return dexOut;
     }
@@ -195,7 +195,7 @@ public final class DexMerger {
         int wastedByteCount = writerSizes.size() - compactedSizes.size();
         if (wastedByteCount >  + compactWasteThreshold) {
             DexMerger compacter = new DexMerger(
-                    dexOut, new Dex(), CollisionPolicy.FAIL, compactedSizes);
+                    dexOut, new Dex(0), CollisionPolicy.FAIL, compactedSizes);
             result = compacter.mergeDexes();
             System.out.printf("Result compacted from %.1fKiB to %.1fKiB to save %.1fKiB%n",
                     dexOut.getLength() / 1024f,
@@ -1021,6 +1021,7 @@ public final class DexMerger {
         public WriterSizes(Dex a, Dex b) {
             plus(a.getTableOfContents(), false);
             plus(b.getTableOfContents(), false);
+            fourByteAlign();
         }
 
         public WriterSizes(DexMerger dexMerger) {
@@ -1039,7 +1040,7 @@ public final class DexMerger {
             annotation = dexMerger.annotationOut.used();
         }
 
-        public void plus(TableOfContents contents, boolean exact) {
+        private void plus(TableOfContents contents, boolean exact) {
             idsDefs += contents.stringIds.size * SizeOf.STRING_ID_ITEM
                     + contents.typeIds.size * SizeOf.TYPE_ID_ITEM
                     + contents.protoIds.size * SizeOf.PROTO_ID_ITEM
@@ -1071,9 +1072,26 @@ public final class DexMerger {
                 // all of the bytes in a debug info section may be uleb/sleb
                 debugInfo += contents.debugInfos.byteCount * 2;
             }
+        }
+
+        private void fourByteAlign() {
+            header = fourByteAlign(header);
+            idsDefs = fourByteAlign(idsDefs);
+            mapList = fourByteAlign(mapList);
+            typeList = fourByteAlign(typeList);
+            classData = fourByteAlign(classData);
+            code = fourByteAlign(code);
+            stringData = fourByteAlign(stringData);
+            debugInfo = fourByteAlign(debugInfo);
+            encodedArray = fourByteAlign(encodedArray);
+            annotationsDirectory = fourByteAlign(annotationsDirectory);
+            annotationsSet = fourByteAlign(annotationsSet);
+            annotationsSetRefList = fourByteAlign(annotationsSetRefList);
+            annotation = fourByteAlign(annotation);
+        }
 
-            typeList = Dex.fourByteAlign(typeList);
-            code = Dex.fourByteAlign(code);
+        private static int fourByteAlign(int position) {
+            return (position + 3) & ~3;
         }
 
         public int size() {