Remove Closer usage where is not mandatory - Remove closer from readProguardMap because the method uses multi-thread. - Remove closer from readMainDexList because the method uses multi-thread. - Remove closer from ClassReader because the class uses multi-thread. - Remove closer allows to close files earlier and can avoid too many open files exception. Bug: 64780725 Change-Id: Id6ee28c300f95470b0c873e6e5286d4aed7ec922
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java index f30ee0a..da90e82 100644 --- a/src/main/java/com/android/tools/r8/R8.java +++ b/src/main/java/com/android/tools/r8/R8.java
@@ -434,7 +434,7 @@ options.proguardConfiguration.getPrintMappingFile(), System.out, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); - outputApp.writeProguardMap(closer, mapOut); + outputApp.writeProguardMap(mapOut); } } if (options.proguardConfiguration.isPrintSeeds()) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java index 2553650..aa32b12 100644 --- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java +++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -75,7 +75,7 @@ throws IOException, ExecutionException { timing.begin("DexApplication.read"); final DexApplication.Builder builder = new DexApplication.Builder(itemFactory, timing); - try (Closer closer = Closer.create()) { + try { List<Future<?>> futures = new ArrayList<>(); // Still preload some of the classes, primarily for two reasons: // (a) class lazy loading is not supported for DEX files @@ -84,9 +84,9 @@ // (b) some of the class file resources don't provide information // about class descriptor. // TODO: try and preload less classes. - readProguardMap(builder, executorService, futures, closer); - readMainDexList(builder, executorService, futures, closer); - ClassReader classReader = new ClassReader(executorService, futures, closer); + readProguardMap(builder, executorService, futures); + readMainDexList(builder, executorService, futures); + ClassReader classReader = new ClassReader(executorService, futures); classReader.readSources(); ThreadUtils.awaitFutures(futures); classReader.initializeLazyClassCollection(builder); @@ -130,13 +130,12 @@ } private void readProguardMap(DexApplication.Builder builder, ExecutorService executorService, - List<Future<?>> futures, Closer closer) + List<Future<?>> futures) throws IOException { // Read the Proguard mapping file in parallel with DexCode and DexProgramClass items. if (inputApp.hasProguardMap()) { futures.add(executorService.submit(() -> { - try { - InputStream map = inputApp.getProguardMap(closer); + try (InputStream map = inputApp.getProguardMap()) { builder.setProguardMap(ProguardMapReader.mapperFromInputStream(map)); } catch (IOException e) { throw new RuntimeException(e); @@ -146,18 +145,18 @@ } private void readMainDexList(DexApplication.Builder builder, ExecutorService executorService, - List<Future<?>> futures, Closer closer) + List<Future<?>> futures) throws IOException { if (inputApp.hasMainDexList()) { futures.add(executorService.submit(() -> { - try { - for (Resource resource : inputApp.getMainDexListResources()) { - InputStream input = closer.register(resource.getStream()); + for (Resource resource : inputApp.getMainDexListResources()) { + try (InputStream input = resource.getStream()) { builder.addToMainDexList(MainDexList.parse(input, itemFactory)); + } catch (IOException e) { + throw new RuntimeException(e); } - } catch (IOException e) { - throw new RuntimeException(e); } + builder.addToMainDexList( inputApp.getMainDexClasses() .stream() @@ -170,7 +169,6 @@ private final class ClassReader { private final ExecutorService executorService; private final List<Future<?>> futures; - private final Closer closer; // We use concurrent queues to collect classes // since the classes can be collected concurrently. @@ -180,10 +178,9 @@ // Jar application reader to share across all class readers. private final JarApplicationReader application = new JarApplicationReader(options); - ClassReader(ExecutorService executorService, List<Future<?>> futures, Closer closer) { + ClassReader(ExecutorService executorService, List<Future<?>> futures) { this.executorService = executorService; this.futures = futures; - this.closer = closer; } private <T extends DexClass> void readDexSources(List<Resource> dexSources, @@ -192,9 +189,11 @@ List<DexFileReader> fileReaders = new ArrayList<>(dexSources.size()); int computedMinApiLevel = options.minApiLevel; for (Resource input : dexSources) { - DexFile file = new DexFile(closer.register(input.getStream())); - computedMinApiLevel = verifyOrComputeMinApiLevel(computedMinApiLevel, file); - fileReaders.add(new DexFileReader(file, classKind, itemFactory)); + try (InputStream is = input.getStream()) { + DexFile file = new DexFile(is); + computedMinApiLevel = verifyOrComputeMinApiLevel(computedMinApiLevel, file); + fileReaders.add(new DexFileReader(file, classKind, itemFactory)); + } } options.minApiLevel = computedMinApiLevel; for (DexFileReader reader : fileReaders) { @@ -216,7 +215,9 @@ JarClassFileReader reader = new JarClassFileReader( application, classKind.bridgeConsumer(classes::add)); for (Resource input : classSources) { - reader.read(DEFAULT_DEX_FILENAME, classKind, closer.register(input.getStream())); + try (InputStream is = input.getStream()) { + reader.read(DEFAULT_DEX_FILENAME, classKind, is); + } } }
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java index 2480417..006dc1a 100644 --- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java +++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -212,8 +212,8 @@ /** * Get the input stream of the proguard-map resource if it exists. */ - public InputStream getProguardMap(Closer closer) throws IOException { - return proguardMap == null ? null : closer.register(proguardMap.getStream()); + public InputStream getProguardMap() throws IOException { + return proguardMap == null ? null : proguardMap.getStream(); } /** @@ -382,10 +382,11 @@ } } - public void writeProguardMap(Closer closer, OutputStream out) throws IOException { - InputStream input = getProguardMap(closer); - assert input != null; - out.write(ByteStreams.toByteArray(input)); + public void writeProguardMap(OutputStream out) throws IOException { + try (InputStream input = getProguardMap()) { + assert input != null; + out.write(ByteStreams.toByteArray(input)); + } } public void writeProguardSeeds(Closer closer, OutputStream out) throws IOException {
diff --git a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java index 66137df..d5f9c6a 100644 --- a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java +++ b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
@@ -70,10 +70,8 @@ .addProguardConfigurationFiles(keepRulesPath) .build()); if (androidApp.hasProguardMap()) { - try (Closer closer = Closer.create()) { - androidApp.writeProguardMap(closer, new FileOutputStream( + androidApp.writeProguardMap(new FileOutputStream( Paths.get(tmpOutputDir.getRoot().getCanonicalPath(), DEFAULT_MAP_FILENAME).toFile())); - } } }
diff --git a/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java b/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java index 72b452f..1426a0f 100644 --- a/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java +++ b/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java
@@ -30,6 +30,7 @@ import com.google.common.collect.Maps; import com.google.common.io.Closer; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; @@ -115,8 +116,8 @@ ToolHelper.runR8(command, (options) -> options.skipDebugLineNumberOpt = !compressRanges); ClassNameMapper classNameMapper; - try (Closer closer = Closer.create()) { - classNameMapper = ProguardMapReader.mapperFromInputStream(result.getProguardMap(closer)); + try (InputStream is = result.getProguardMap()) { + classNameMapper = ProguardMapReader.mapperFromInputStream(is); } if (compressRanges) { classNameMapper.forAllClassNamings(this::ensureRangesAreUniquePerClass);