Status Update
Comments
ja...@jamesonwilliams.com <ja...@jamesonwilliams.com> #3
ze...@google.com <ze...@google.com> #4
ja...@jamesonwilliams.com <ja...@jamesonwilliams.com> #5
ze...@google.com <ze...@google.com> #6
The list methods shows duplicates as it lists the method table which are just method references. It is allowed and expected to have references in multiple classes*.dex files.
Decompiling the APK does not show any duplicate classes. The only j$ definitions are in classes2.dex and there is no duplicate of Lj$/$r8$wrapper$java$util$function$Supplier$-WRP
This does not look like a dup of
We will keep looking for the cause and update here if we need more info from your side.
cl...@google.com <cl...@google.com> #7
Have you tried to do Files > invalidate caches / restart ? It looks like a cache issue.
In comment 1 I can read the problem comes from: Caused by: java.lang.NoClassDefFoundError: $r8$wrapper$java$util$function$Supplier$-WRP In comment 3 I can read the problem comes from: Caused by: java.lang.NoClassDefFoundError: j$.$r8$wrapper$java$util$function$Supplier$-WRP
That gets me confused, if the problem comes from the prefix, then it may be a cache issue.
I will look a bit more in the apk.
ja...@jamesonwilliams.com <ja...@jamesonwilliams.com> #8
I have used ./gradlew clean build
after making each change/update, above.
For sake of completeness, I just opened Android Studio, cleared/invalidated caches, closed Android Studio, and ran ./gradlew clean build
again. I still do see this:
Caused by: java.lang.NoClassDefFoundError: j$.$r8$wrapper$java$util$function$Supplier$-WRP
When I used the default version of R8 that is pulled in by Android Studio 4.0.0, and did not set debuggable false
on my debug build, I saw the $r8
prefix. When I use 2.1.47 of r8, and do set debuggable false
, I get the j$.$r8
prefix.
Attached, please find a tarball of an Android Studio project that will repro this issue.
cl...@google.com <cl...@google.com> #9
OK I got it.
This is related to
Basically what is going on is that you are trying to use the API ThreadLocal#withInitial, which was added in API 26, from a runtime device of API 21. ThreadLocal#withInitial is not part of desugared library, hence the method is not available. That is your problem, this is not possible.
Now the underlying problem is the error message. Below I discuss about it.
What is possible is to write code such as:
ThreadLocal<?> tl;
if (API >= 26) {
tl = ThreadLocal.withInitial(supplier);
} else {
// Some fall-back code set to tl.
}
The code shown is supposed to work, but we have no way in D8/R8 to figure out if we're in a branch/method protected by an API level guard.
To make that work, the API call ThreadLocal#withInitial uses internally API conversion, to convert j$..Supplier to java..Supplier. That conversion is invalid under low API level, ending up with the ClassNotFound problem.
We had a similar report once before, and after discussing with our techlead, we decided that at this point, it seemed the runtime performance and code size overhead of raising the proper error message here (NoSuchMethod ThreadLocal#withInitial instead of the ClassNotFound) was not worth it.
Now this is the second report and it was not obvious what the problem was. I know that @zerny was in favor of raising the right error last time despite the runtime performance overhead and code size overhead. So I'll discuss again tomorrow at our team meeting what we want to do here. I wanted to check with the studio people if it was possible to raise the proper message.
Here is the corresponding smali that helped me figured out the problem:
.method static constructor <clinit>()V
.locals 1
.line 58
sget-object v0, Lsoftware/amazon/awssdk/auth/signer/internal/-$$Lambda$AbstractAwsSigner$2E36gWY0haa6ax303A5PcwgkmX8;->INSTANCE:Lsoftware/amazon/awssdk/auth/signer/internal/-$$Lambda$AbstractAwsSigner$2E36gWY0haa6ax303A5PcwgkmX8;
invoke-static {v0}, Lj$/$r8$wrapper$java$util$function$Supplier$-WRP;->convert(Lj$/util/function/Supplier;)Ljava/util/function/Supplier;
move-result-object v0
invoke-static {v0}, Ljava/lang/ThreadLocal;->withInitial(Ljava/util/function/Supplier;)Ljava/lang/ThreadLocal;
move-result-object v0
sput-object v0, Lsoftware/amazon/awssdk/auth/signer/internal/AbstractAwsSigner;->SHA256_MESSAGE_DIGEST:Ljava/lang/ThreadLocal;
return-void
.end method
ja...@jamesonwilliams.com <ja...@jamesonwilliams.com> #10
Thanks! I agree the error message could be improved.
Per the title, my original report here is really a feature request: "Can you add support for ThreadLocal#withInitial(...)
into the desugaring library?"
I have also
cl...@google.com <cl...@google.com> #11
I will add ThreadLocal#withInitial to the desugared library wanted features hotlist, we'll see what we can do. It's not going to happen anytime soon though (at the very least not this quarter), so it's probably better if you build a work-around for now.
sg...@google.com <sg...@google.com> #12
Given a supplier
Supplier<T> supplier = ...
Could
ThreadLocal<T> threadLocal = ThreadLocal.withInitial(supplier)
be desugared to
class SynthesizedThreadLocalSubClass extends ThreadLocal<T> {
private Supplier<T> supplier;
SynthesizedThreadLocalSubClass(Supplier<T> supplier) {
this.supplier = supplier;
}
protected T initialValue() {
return supplier.get();
}
}
ThreadLocal<T> threadLocal = new SynthesizedThreadLocalSubClass(supplier);
?
That could allow this to be handled using backporting if backporting is extended to synthesize the subclass SynthesizedThreadLocalSubClass
of ThreadLocal
if required (that is if ThreadLocal.withInitial
is used in the app).
mi...@gmail.com <mi...@gmail.com> #13
Any update on this?
cl...@google.com <cl...@google.com> #14
We've not worked on implementing a work-around for ThreadLocal.withInitial() so far.
@sgjesse should we try this quarter/next quarter?
sg...@google.com <sg...@google.com>
ap...@google.com <ap...@google.com> #15
Branch: main
commit a6f2739d4969ce085b93529c7cd20cc4cfee176b
Author: Søren Gjesse <sgjesse@google.com>
Date: Thu Sep 08 16:10:10 2022
Backport ThreadLocal.withInitial when Supplier is present
This will backport ThreadLocal.withInitial(java.util.function.Supplier)
when java.util.function.Supplier is present at runtime.
Without desugared library this makes the method usable from API level
24 (when Supplier was introduced) instead of from API level 26 (when
withInitial was introduced).
With desugared library the method is always usable as Supplier is
included in all desugared library versions.
Bug:
Change-Id: I536879372d903d15b182a2ef071adf01361c8f01
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethodDesugaringEventConsumer.java
M src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
M src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #16
Branch: main
commit b595f9b29de6e925a1a8e82f02a74a6d0da4db2c
Author: Søren Gjesse <sgjesse@google.com>
Date: Tue Sep 13 12:49:15 2022
Fix stack height for rewrite or ThreadLocal.withInitial
Bug:
Change-Id: I89d10b9d45357b57d32db47737035f38a5cb27f8
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #17
Branch: 3.2
commit 65092faa0276ccb00a37b8d35a10038cbbdec5fb
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 11:08:57 2022
Version 3.2.81
Contains changes to resolve cherry-pick issues.
Bug:
Change-Id: I95cf2b7ef6dd6a7eafbff2a4735c7cd6d60f35de
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
M src/main/java/com/android/tools/r8/Version.java
ap...@google.com <ap...@google.com> #18
Branch: 3.2
commit 703819c5fa4cff78373dee829761f807574ec2b9
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 11:07:00 2022
Fix stack height for rewrite or ThreadLocal.withInitial
Bug:
Change-Id: I89d10b9d45357b57d32db47737035f38a5cb27f8
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #19
Branch: 3.2
commit 3931c5a1299bf1c2df1bfae06a9b954d2dc87b52
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 11:06:28 2022
Backport ThreadLocal.withInitial when Supplier is present
This will backport ThreadLocal.withInitial(java.util.function.Supplier)
when java.util.function.Supplier is present at runtime.
Without desugared library this makes the method usable from API level
24 (when Supplier was introduced) instead of from API level 26 (when
withInitial was introduced).
With desugared library the method is always usable as Supplier is
included in all desugared library versions.
Bug:
Change-Id: I536879372d903d15b182a2ef071adf01361c8f01
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethodDesugaringEventConsumer.java
M src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
M src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
sg...@google.com <sg...@google.com>
sg...@google.com <sg...@google.com>
ap...@google.com <ap...@google.com> #20
Branch: 4.0
commit 3b4722724a1460a5f0a245089210bf4e42cada23
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 13:02:41 2022
Version 4.0.29
Bug:
Change-Id: I66dd4552b850077b8abfa87fb2760d7b17cdde62
M src/main/java/com/android/tools/r8/Version.java
ap...@google.com <ap...@google.com> #21
Branch: 4.0
commit 654dcebcc75dbfa59b40ded2f5b1e87195af94a2
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 13:02:32 2022
Fix stack height for rewrite or ThreadLocal.withInitial
Bug:
Change-Id: I89d10b9d45357b57d32db47737035f38a5cb27f8
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #22
Branch: 4.0
commit edf6432389f51e54f165a04fe32b0522e92306ad
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 12:57:52 2022
Backport ThreadLocal.withInitial when Supplier is present
This will backport ThreadLocal.withInitial(java.util.function.Supplier)
when java.util.function.Supplier is present at runtime.
Without desugared library this makes the method usable from API level
24 (when Supplier was introduced) instead of from API level 26 (when
withInitial was introduced).
With desugared library the method is always usable as Supplier is
included in all desugared library versions.
Bug:
Change-Id: I536879372d903d15b182a2ef071adf01361c8f01
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethodDesugaringEventConsumer.java
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
M src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #23
Branch: 3.3
commit d6e7e48c4ae98e002e962c070f5dd310c85a59e0
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 12:36:52 2022
Version 3.3.79
Contains changes to resolve cherry-pick issues.
Bug:
Change-Id: I65e2242cdf294aabc03dd728e63c68cea653c92a
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
M src/main/java/com/android/tools/r8/Version.java
ap...@google.com <ap...@google.com> #24
Branch: 3.3
commit a9d35293e7c3e9bd7544dadc1aa3afac6829ec23
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 12:36:33 2022
Fix stack height for rewrite or ThreadLocal.withInitial
Bug:
Change-Id: I89d10b9d45357b57d32db47737035f38a5cb27f8
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #25
Branch: 3.3
commit c460eb8a5ba603d8833d02d78b92321416ae78ae
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 12:35:53 2022
Backport ThreadLocal.withInitial when Supplier is present
This will backport ThreadLocal.withInitial(java.util.function.Supplier)
when java.util.function.Supplier is present at runtime.
Without desugared library this makes the method usable from API level
24 (when Supplier was introduced) instead of from API level 26 (when
withInitial was introduced).
With desugared library the method is always usable as Supplier is
included in all desugared library versions.
Bug:
Change-Id: I536879372d903d15b182a2ef071adf01361c8f01
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethodDesugaringEventConsumer.java
M src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
M src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
ap...@google.com <ap...@google.com> #26
Branch: 4.0
commit 654dcebcc75dbfa59b40ded2f5b1e87195af94a2
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 13:02:32 2022
Fix stack height for rewrite or ThreadLocal.withInitial
Bug:
Change-Id: I89d10b9d45357b57d32db47737035f38a5cb27f8
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
ap...@google.com <ap...@google.com> #27
Branch: 4.0
commit edf6432389f51e54f165a04fe32b0522e92306ad
Author: Søren Gjesse <sgjesse@google.com>
Date: Wed Sep 14 12:57:52 2022
Backport ThreadLocal.withInitial when Supplier is present
This will backport ThreadLocal.withInitial(java.util.function.Supplier)
when java.util.function.Supplier is present at runtime.
Without desugared library this makes the method usable from API level
24 (when Supplier was introduced) instead of from API level 26 (when
withInitial was introduced).
With desugared library the method is always usable as Supplier is
included in all desugared library versions.
Bug:
Change-Id: I536879372d903d15b182a2ef071adf01361c8f01
M src/main/java/com/android/tools/r8/graph/DexItemFactory.java
M src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
M src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethodDesugaringEventConsumer.java
M src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportWithDesugaredLibraryTest.java
M src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
A src/test/java/com/android/tools/r8/desugar/backports/ThreadLocalBackportTest.java
Description
What I'm Doing
I am trying to use core library desugaring with Android Studio 4.0.0. I use AGP 4.0.0, Gradle 6.5.1.
I am using an Android 5 (API 21) device.
I have:
And:
I include some simple code:
What Goes Wrong
This will build, and install. But, at runtime, on the API 21 device, the application crashes:
Why It Goes Wrong (Maybe)
The line it is unhappy about is in
ThreadLocal
'swithInitial
static method, which takes ajava.util.function.Supplier
.ThreadLocal
is NOT listed in theAdditional Information
The build did include copious warnings.
Expected Behavior
Desugaring tools produce working implementation for
ThreadLocal.withInitial(Supplier)
. The code functions on an Android 5 / API 21 device.