feat: use MemoryDataStore instead of FileDataStore

This commit is contained in:
oSumAtrIX 2023-08-11 02:10:46 +02:00
parent ac410e52eb
commit 89a3a37f1d
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
2 changed files with 30 additions and 36 deletions

View File

@ -17,6 +17,7 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@ -31,7 +32,7 @@ import com.android.tools.smali.dexlib2.iface.ClassDef;
import com.android.tools.smali.dexlib2.iface.DexFile;
import com.android.tools.smali.dexlib2.writer.DexWriter;
import com.android.tools.smali.dexlib2.writer.io.DexDataStore;
import com.android.tools.smali.dexlib2.writer.io.FileDataStore;
import com.android.tools.smali.dexlib2.writer.io.MemoryDataStore;
import com.android.tools.smali.dexlib2.writer.pool.DexPool;
public class DexIO {
@ -65,18 +66,14 @@ public class DexIO {
dexPool.writeTo(dataStore);
}
static void writeMultiDexDirectorySingleThread(boolean multiDex, File directory, DexFileNameIterator nameIterator,
static void writeMultiDexDirectorySingleThread(Map<String, MemoryDataStore> output, DexFileNameIterator nameIterator,
DexFile dexFile, int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize, DexIO.Logger logger)
throws IOException {
Set<? extends ClassDef> classes = dexFile.getClasses();
if (!multiDex) {
minMainDexClassCount = classes.size();
minimalMainDex = false;
}
Object lock = new Object();
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (lock) { // avoid multiple synchronizations in single-threaded mode
writeMultiDexDirectoryCommon(directory, nameIterator, Iterators.peekingIterator(classes.iterator()),
writeMultiDexDirectoryCommon(output, nameIterator, Iterators.peekingIterator(classes.iterator()),
minMainDexClassCount, minimalMainDex, dexFile.getOpcodes(), maxDexPoolSize, logger, lock);
}
}
@ -85,7 +82,7 @@ public class DexIO {
private static final int PER_THREAD_BATCH_SIZE = 100;
static void writeMultiDexDirectoryMultiThread(int threadCount, final File directory,
static void writeMultiDexDirectoryMultiThread(int threadCount, final Map<String, MemoryDataStore> output,
final DexFileNameIterator nameIterator, final DexFile dexFile, final int maxDexPoolSize,
final DexIO.Logger logger) throws IOException {
Iterator<? extends ClassDef> classIterator = dexFile.getClasses().iterator();
@ -99,7 +96,7 @@ public class DexIO {
callables.add(new Callable<Void>() {
@Override
public Void call() throws IOException {
writeMultiDexDirectoryCommon(directory, nameIterator, batchedIterator, 0, false,
writeMultiDexDirectoryCommon(output, nameIterator, batchedIterator, 0, false,
dexFile.getOpcodes(), maxDexPoolSize, logger, lock);
return null;
}
@ -130,7 +127,7 @@ public class DexIO {
// Common Code
private static void writeMultiDexDirectoryCommon(File directory, DexFileNameIterator nameIterator,
private static void writeMultiDexDirectoryCommon(Map<String, MemoryDataStore> output, DexFileNameIterator nameIterator,
PeekingIterator<? extends ClassDef> classIterator, int minMainDexClassCount, boolean minimalMainDex,
Opcodes opcodes, int maxDexPoolSize, DexIO.Logger logger, Object lock) throws IOException {
do {
@ -149,17 +146,17 @@ public class DexIO {
classIterator.next();
fileClassCount++;
}
File file;
String dexName;
MemoryDataStore memoryDataStore = new MemoryDataStore();
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (lock) {
String name = nameIterator.next();
file = new File(directory, name);
if (logger != null) logger.log(directory, name, fileClassCount);
dexName = nameIterator.next();
if (classIterator instanceof BatchedIterator) {
((BatchedIterator<?>) classIterator).preloadBatch();
}
}
dexPool.writeTo(new FileDataStore(file));
dexPool.writeTo(memoryDataStore);
output.put(dexName, memoryDataStore);
minMainDexClassCount = 0;
minimalMainDex = false;
} while (classIterator.hasNext());

View File

@ -14,11 +14,13 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.android.tools.smali.dexlib2.Opcodes;
import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile;
import com.android.tools.smali.dexlib2.iface.DexFile;
import com.android.tools.smali.dexlib2.iface.MultiDexContainer;
import com.android.tools.smali.dexlib2.writer.io.MemoryDataStore;
public class MultiDexIO {
@ -65,51 +67,46 @@ public class MultiDexIO {
// Write
public static int writeDexFile(boolean multiDex, File file, DexFileNamer namer, DexFile dexFile,
public static int writeDexFile(boolean multiDex, Map<String, MemoryDataStore> output, DexFileNamer namer, DexFile dexFile,
int maxDexPoolSize, DexIO.Logger logger) throws IOException {
return writeDexFile(multiDex, 1, file, namer, dexFile, maxDexPoolSize, logger);
return writeDexFile(multiDex, 1, output, namer, dexFile, maxDexPoolSize, logger);
}
public static int writeDexFile(boolean multiDex, int threadCount, File file, DexFileNamer namer, DexFile dexFile,
public static int writeDexFile(boolean multiDex, int threadCount, Map<String, MemoryDataStore> output, DexFileNamer namer, DexFile dexFile,
int maxDexPoolSize, DexIO.Logger logger) throws IOException {
return writeDexFile(multiDex, threadCount, file, namer, dexFile, 0, false, maxDexPoolSize, logger);
return writeDexFile(multiDex, threadCount, output, namer, dexFile, 0, false, maxDexPoolSize, logger);
}
public static int writeDexFile(boolean multiDex, File file, DexFileNamer namer, DexFile dexFile,
public static int writeDexFile(boolean multiDex, Map<String, MemoryDataStore> output, DexFileNamer namer, DexFile dexFile,
int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize,
DexIO.Logger logger) throws IOException {
return writeDexFile(multiDex, 1, file, namer, dexFile, minMainDexClassCount, minimalMainDex, maxDexPoolSize,
return writeDexFile(multiDex, 1, output, namer, dexFile, minMainDexClassCount, minimalMainDex, maxDexPoolSize,
logger);
}
public static int writeDexFile(boolean multiDex, int threadCount, File file, DexFileNamer namer, DexFile dexFile,
public static int writeDexFile(boolean multiDex, int threadCount, Map<String, MemoryDataStore> output, DexFileNamer namer, DexFile dexFile,
int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize,
DexIO.Logger logger) throws IOException {
if (file.isDirectory()) {
return writeMultiDexDirectory(multiDex, threadCount, file, namer, dexFile, minMainDexClassCount,
minimalMainDex, maxDexPoolSize, logger);
} else {
if (multiDex) throw new UnsupportedOperationException(
"Must output to a directory if multi-dex mode is enabled");
RawDexIO.writeRawDexFile(file, dexFile, maxDexPoolSize, logger);
return 1;
}
if (!multiDex) throw new UnsupportedOperationException(
"Non-multidex is no longer supported, please use the official multidexlib2 for that."
);
return writeMultiDexDirectory(threadCount, output, namer, dexFile, minMainDexClassCount,
minimalMainDex, maxDexPoolSize, logger);
}
public static int writeMultiDexDirectory(boolean multiDex, int threadCount, File directory, DexFileNamer namer,
public static int writeMultiDexDirectory(int threadCount, Map<String, MemoryDataStore> output, DexFileNamer namer,
DexFile dexFile, int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize, DexIO.Logger logger)
throws IOException {
purgeMultiDexDirectory(multiDex, directory, namer);
DexFileNameIterator nameIterator = new DexFileNameIterator(namer);
if (threadCount <= 0) {
threadCount = Runtime.getRuntime().availableProcessors();
if (threadCount > DEFAULT_MAX_THREADS) threadCount = DEFAULT_MAX_THREADS;
}
if (threadCount > 1 && multiDex && minMainDexClassCount == 0 && !minimalMainDex) {
DexIO.writeMultiDexDirectoryMultiThread(threadCount, directory, nameIterator, dexFile, maxDexPoolSize,
if (threadCount > 1 && minMainDexClassCount == 0 && !minimalMainDex) {
DexIO.writeMultiDexDirectoryMultiThread(threadCount, output, nameIterator, dexFile, maxDexPoolSize,
logger);
} else {
DexIO.writeMultiDexDirectorySingleThread(multiDex, directory, nameIterator, dexFile, minMainDexClassCount,
DexIO.writeMultiDexDirectorySingleThread(output, nameIterator, dexFile, minMainDexClassCount,
minimalMainDex, maxDexPoolSize, logger);
}
return nameIterator.getCount();