From 9833e732a025891c951dc5a2c5cc7e52cca96703 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 9 Oct 2023 04:06:29 +0200 Subject: [PATCH] feat: Use `FileDataStore` instead of `MemoryDataStore` This reverts commit 1dbfaa5921c23df7b9111e874b2f97d58ab3ec2a. Memory usage was too high. --- src/main/java/lanchon/multidexlib2/DexIO.java | 27 +++++++------ .../java/lanchon/multidexlib2/MultiDexIO.java | 39 ++++++++++--------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/main/java/lanchon/multidexlib2/DexIO.java b/src/main/java/lanchon/multidexlib2/DexIO.java index c60df56..97227f6 100644 --- a/src/main/java/lanchon/multidexlib2/DexIO.java +++ b/src/main/java/lanchon/multidexlib2/DexIO.java @@ -17,7 +17,6 @@ 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; @@ -32,7 +31,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.MemoryDataStore; +import com.android.tools.smali.dexlib2.writer.io.FileDataStore; import com.android.tools.smali.dexlib2.writer.pool.DexPool; public class DexIO { @@ -66,14 +65,18 @@ public class DexIO { dexPool.writeTo(dataStore); } - static void writeMultiDexDirectorySingleThread(Map output, DexFileNameIterator nameIterator, + static void writeMultiDexDirectorySingleThread(boolean multiDex, File directory, DexFileNameIterator nameIterator, DexFile dexFile, int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize, DexIO.Logger logger) throws IOException { Set 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(output, nameIterator, Iterators.peekingIterator(classes.iterator()), + writeMultiDexDirectoryCommon(directory, nameIterator, Iterators.peekingIterator(classes.iterator()), minMainDexClassCount, minimalMainDex, dexFile.getOpcodes(), maxDexPoolSize, logger, lock); } } @@ -82,7 +85,7 @@ public class DexIO { private static final int PER_THREAD_BATCH_SIZE = 100; - static void writeMultiDexDirectoryMultiThread(int threadCount, final Map output, + static void writeMultiDexDirectoryMultiThread(int threadCount, final File directory, final DexFileNameIterator nameIterator, final DexFile dexFile, final int maxDexPoolSize, final DexIO.Logger logger) throws IOException { Iterator classIterator = dexFile.getClasses().iterator(); @@ -96,7 +99,7 @@ public class DexIO { callables.add(new Callable() { @Override public Void call() throws IOException { - writeMultiDexDirectoryCommon(output, nameIterator, batchedIterator, 0, false, + writeMultiDexDirectoryCommon(directory, nameIterator, batchedIterator, 0, false, dexFile.getOpcodes(), maxDexPoolSize, logger, lock); return null; } @@ -127,7 +130,7 @@ public class DexIO { // Common Code - private static void writeMultiDexDirectoryCommon(Map output, DexFileNameIterator nameIterator, + private static void writeMultiDexDirectoryCommon(File directory, DexFileNameIterator nameIterator, PeekingIterator classIterator, int minMainDexClassCount, boolean minimalMainDex, Opcodes opcodes, int maxDexPoolSize, DexIO.Logger logger, Object lock) throws IOException { do { @@ -146,17 +149,17 @@ public class DexIO { classIterator.next(); fileClassCount++; } - String dexName; - MemoryDataStore memoryDataStore = new MemoryDataStore(); + File file; //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (lock) { - dexName = nameIterator.next(); + String name = nameIterator.next(); + file = new File(directory, name); + if (logger != null) logger.log(directory, name, fileClassCount); if (classIterator instanceof BatchedIterator) { ((BatchedIterator) classIterator).preloadBatch(); } } - dexPool.writeTo(memoryDataStore); - output.put(dexName, memoryDataStore); + dexPool.writeTo(new FileDataStore(file)); minMainDexClassCount = 0; minimalMainDex = false; } while (classIterator.hasNext()); diff --git a/src/main/java/lanchon/multidexlib2/MultiDexIO.java b/src/main/java/lanchon/multidexlib2/MultiDexIO.java index 7310db8..0815493 100644 --- a/src/main/java/lanchon/multidexlib2/MultiDexIO.java +++ b/src/main/java/lanchon/multidexlib2/MultiDexIO.java @@ -14,13 +14,11 @@ 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 { @@ -67,46 +65,51 @@ public class MultiDexIO { // Write - public static int writeDexFile(boolean multiDex, Map output, DexFileNamer namer, DexFile dexFile, + public static int writeDexFile(boolean multiDex, File file, DexFileNamer namer, DexFile dexFile, int maxDexPoolSize, DexIO.Logger logger) throws IOException { - return writeDexFile(multiDex, 1, output, namer, dexFile, maxDexPoolSize, logger); + return writeDexFile(multiDex, 1, file, namer, dexFile, maxDexPoolSize, logger); } - public static int writeDexFile(boolean multiDex, int threadCount, Map output, DexFileNamer namer, DexFile dexFile, + public static int writeDexFile(boolean multiDex, int threadCount, File file, DexFileNamer namer, DexFile dexFile, int maxDexPoolSize, DexIO.Logger logger) throws IOException { - return writeDexFile(multiDex, threadCount, output, namer, dexFile, 0, false, maxDexPoolSize, logger); + return writeDexFile(multiDex, threadCount, file, namer, dexFile, 0, false, maxDexPoolSize, logger); } - public static int writeDexFile(boolean multiDex, Map output, DexFileNamer namer, DexFile dexFile, + public static int writeDexFile(boolean multiDex, File file, DexFileNamer namer, DexFile dexFile, int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize, DexIO.Logger logger) throws IOException { - return writeDexFile(multiDex, 1, output, namer, dexFile, minMainDexClassCount, minimalMainDex, maxDexPoolSize, + return writeDexFile(multiDex, 1, file, namer, dexFile, minMainDexClassCount, minimalMainDex, maxDexPoolSize, logger); } - public static int writeDexFile(boolean multiDex, int threadCount, Map output, DexFileNamer namer, DexFile dexFile, + public static int writeDexFile(boolean multiDex, int threadCount, File file, DexFileNamer namer, DexFile dexFile, int minMainDexClassCount, boolean minimalMainDex, int maxDexPoolSize, DexIO.Logger logger) throws IOException { - 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); + 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; + } } - public static int writeMultiDexDirectory(int threadCount, Map output, DexFileNamer namer, + public static int writeMultiDexDirectory(boolean multiDex, int threadCount, File directory, 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 && minMainDexClassCount == 0 && !minimalMainDex) { - DexIO.writeMultiDexDirectoryMultiThread(threadCount, output, nameIterator, dexFile, maxDexPoolSize, + if (threadCount > 1 && multiDex && minMainDexClassCount == 0 && !minimalMainDex) { + DexIO.writeMultiDexDirectoryMultiThread(threadCount, directory, nameIterator, dexFile, maxDexPoolSize, logger); } else { - DexIO.writeMultiDexDirectorySingleThread(output, nameIterator, dexFile, minMainDexClassCount, + DexIO.writeMultiDexDirectorySingleThread(multiDex, directory, nameIterator, dexFile, minMainDexClassCount, minimalMainDex, maxDexPoolSize, logger); } return nameIterator.getCount();