Fixed
Status Update
Comments
uc...@google.com <uc...@google.com>
vs...@jetbrains.com <vs...@jetbrains.com> #2
See small performance investigation: https://github.com/Kotlin/kotlinx.coroutines/issues/878
A lot of `load()` footprint can be cut off if ServiceLoader implementation will stop verifying JAR's integrity.
Why I think this is a safe change for Android: JAR verification is used by ServiceLoader not because it explicitly opts in that, but because it is a default behaviour of `URL.openStream()`.
It *does not* validate signer certificate, so it is completely useless from the security standpoint of view. It basically checks that given JAR is not corrupted, but this check can be done during JAR -> dex conversion in compile time and completely avoided in runtime.
A lot of `load()` footprint can be cut off if ServiceLoader implementation will stop verifying JAR's integrity.
Why I think this is a safe change for Android: JAR verification is used by ServiceLoader not because it explicitly opts in that, but because it is a default behaviour of `URL.openStream()`.
It *does not* validate signer certificate, so it is completely useless from the security standpoint of view. It basically checks that given JAR is not corrupted, but this check can be done during JAR -> dex conversion in compile time and completely avoided in runtime.
jv...@google.com <jv...@google.com> #3
I'm not sure R8 is the best place to do this. ProGuard & R8 is only used by a small amount of users and for those only in their release builds. This might be something we want to do as a separate asm rewrite phase or maybe as a desugaring in D8..
lo...@gmail.com <lo...@gmail.com> #4
I agree, D8 desugaring is the best place for this. Has there been any progress? I'd like to alpha/beta test this.
ja...@gmail.com <ja...@gmail.com> #5
With R8 now tracking calls to `ServiceLoader.load` through the `META-INF/services/` file to the referenced subtypes, this should now be trivial to implement.
Whether it should apply in D8 or not shouldn't inhibit it coming to R8 sooner rather than later.
Whether it should apply in D8 or not shouldn't inhibit it coming to R8 sooner rather than later.
ch...@google.com <ch...@google.com>
mk...@google.com <mk...@google.com>
ap...@google.com <ap...@google.com> #6
Project: r8
Branch: master
commit b027e3c0b123bd4a9397ff210e40293c1381d1a8
Author: Morten Krogh-Jespersen <mkroghj@google.com>
Date: Fri Apr 05 15:05:49 2019
Rewrite of ServiceLoader.load to NewInstance when possible
Users using unreleased versions of R8 in kotlin projects can observe
different behaviour between versions as a result of using
ServiceLoader.load for reading kotlin metadata. This is because
multiple service loaders for a service will now exist on the class
path.
This CL will eliminate the ServiceLoader.load in R8lib by rewriting it
to the known instances.
Bug: 120436373
Bug: 129240946
Change-Id: Ie96925e2c3c5e70f2c81f32b9f8eff71b6d7ac91
M src/main/java/com/android/tools/r8/graph/AppServices.java
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
A src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
M src/main/java/com/android/tools/r8/shaking/Enqueuer.java
M src/main/java/com/android/tools/r8/utils/InternalOptions.java
A src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
https://r8-review.googlesource.com/36771
Branch: master
commit b027e3c0b123bd4a9397ff210e40293c1381d1a8
Author: Morten Krogh-Jespersen <mkroghj@google.com>
Date: Fri Apr 05 15:05:49 2019
Rewrite of ServiceLoader.load to NewInstance when possible
Users using unreleased versions of R8 in kotlin projects can observe
different behaviour between versions as a result of using
ServiceLoader.load for reading kotlin metadata. This is because
multiple service loaders for a service will now exist on the class
path.
This CL will eliminate the ServiceLoader.load in R8lib by rewriting it
to the known instances.
Bug: 120436373
Bug: 129240946
Change-Id: Ie96925e2c3c5e70f2c81f32b9f8eff71b6d7ac91
M src/main/java/com/android/tools/r8/graph/AppServices.java
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
A src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
M src/main/java/com/android/tools/r8/shaking/Enqueuer.java
M src/main/java/com/android/tools/r8/utils/InternalOptions.java
A src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
ap...@google.com <ap...@google.com> #7
Project: r8
Branch: master
commit 878ec25559ca91497517345ec3a6c16102b7025c
Author: Morten Krogh-Jespersen <mkroghj@google.com>
Date: Fri Apr 05 23:04:10 2019
Revert "Revert "Rewrite of ServiceLoader.load to NewInstance when possible""
This reverts commit ec8b31146166e479de79a87a841682d2bc879480.
Bug: 120436373
Change-Id: I8edbe04a3f2fab99b9dd00abaa9ade9cb79ddf56
M src/main/java/com/android/tools/r8/graph/AppServices.java
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
A src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
M src/main/java/com/android/tools/r8/shaking/Enqueuer.java
M src/main/java/com/android/tools/r8/utils/InternalOptions.java
A src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
https://r8-review.googlesource.com/36808
Branch: master
commit 878ec25559ca91497517345ec3a6c16102b7025c
Author: Morten Krogh-Jespersen <mkroghj@google.com>
Date: Fri Apr 05 23:04:10 2019
Revert "Revert "Rewrite of ServiceLoader.load to NewInstance when possible""
This reverts commit ec8b31146166e479de79a87a841682d2bc879480.
Bug: 120436373
Change-Id: I8edbe04a3f2fab99b9dd00abaa9ade9cb79ddf56
M src/main/java/com/android/tools/r8/graph/AppServices.java
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
A src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
M src/main/java/com/android/tools/r8/shaking/Enqueuer.java
M src/main/java/com/android/tools/r8/utils/InternalOptions.java
A src/test/java/com/android/tools/r8/rewrite/ServiceLoaderRewritingTest.java
mk...@google.com <mk...@google.com> #8
This is now added to master for R8 and will be included in an upcoming canary release at some point. There is currently no plan for adding it to D8.
We will rewrite calls to ServiceLoader.load when on the form:
ServiceLoader.load(Foo.class, Foo.class.getClassLoader()) and ServiceLoader.load(Foo.class, null).
If you would like to try it out in early alpha-testing, add the following to your build.gradle file:
buildscript {
repositories {
maven {
url "http://storage.googleapis.com/r8-releases/raw/master "
}
}
dependencies {
classpath 'com.android.tools:r8:878ec25559ca91497517345ec3a6c16102b7025c' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:3.0.1' // Or newer
}
}
We will rewrite calls to ServiceLoader.load when on the form:
ServiceLoader.load(Foo.class, Foo.class.getClassLoader()) and ServiceLoader.load(Foo.class, null).
If you would like to try it out in early alpha-testing, add the following to your build.gradle file:
buildscript {
repositories {
maven {
url "
}
}
dependencies {
classpath 'com.android.tools:r8:878ec25559ca91497517345ec3a6c16102b7025c' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:3.0.1' // Or newer
}
}
Description
Examples:
-
-
-
-
In all of these cases the interaction is a call to `load()` followed by a call to `iterator()` to loop over the loaded instances.
Because of how ServiceLoader works, it can be quite slow on Android. And in the cases above, they're likely on the critical path for startup.
By replacing call pairs of `ServiceLoader.load` and then `ServiceLoader.iterator` with direct instantiation and `Arrays.asList` this should result in two things:
* Performance speed up by avoiding resource scanning and reflective instantiation
* The ability to obfuscate/shrink service loader implementations
The trickiest part of this, and which might make such an optimization impossible, is the ClassLoader parameter. In theory, someone could be dynamically loading dexes and passing that as the second parameter.