Status Update
Comments
jv...@google.com <jv...@google.com>
je...@google.com <je...@google.com> #2
ga...@google.com <ga...@google.com> #3
Thank you for filing an issue. Is minifyEnabled true
in the variant you are building?
I tried to reproduce with:
annotation class MyAnnotation
class AnnotatedClass(@MyAnnotation private val someInput: String)
private fun getAnnotations() {
println(AnnotatedClass::class.constructors.single().parameters.first().annotations)
}
but this runs successfully for debug
variant. If you are using code shrinking, can you add -printconfiguration /tmp/out.txt
to keep rules and upload /tmp/out.txt
?
[Deleted User] <[Deleted User]> #4
Sorry, forgot to add that was for release builds, I attached the output of -printconfiguration
ga...@google.com <ga...@google.com> #5
I was able to reproduce with 4.0.0-beta03
using the attached project. Changing build.gradle
to 3.6.1
fixes the issue. Stacktrace I got when running on API 22:
java.lang.IncompatibleClassChangeError: Couldn't find b.j.bv
at libcore.reflect.AnnotationAccess.toAnnotationInstance(AnnotationAccess.java:659)
at libcore.reflect.AnnotationAccess.annotationSetToAnnotations(AnnotationAccess.java:633)
at libcore.reflect.AnnotationAccess.getDeclaredAnnotations(AnnotationAccess.java:161)
at java.lang.Class.getDeclaredAnnotations(Class.java:865)
at b.f0.q.c.h0.b.f1.a.c.b(:83)
at b.f0.q.c.h0.b.f1.a.f$a.a(:55)
at b.f0.q.c.h0.b.f1.a.g.d(:30)
at b.f0.q.c.h0.b.f1.a.g.c(:33)
at b.f0.q.c.h0.d.a.z.n.i$c.d(:62)
at b.f0.q.c.h0.d.a.z.n.i$c.e(:42)
at b.f0.q.c.h0.l.b$j.e(:446)
at b.f0.q.c.h0.d.a.z.n.i.H(:142)
at b.f0.q.c.h0.d.a.z.n.i.J(:132)
at b.f0.q.c.h0.d.a.z.n.d.d(:52)
at b.f0.q.c.h0.j.r.b.d(:33)
at b.f0.q.c.h0.j.r.a.d(:44)
at b.f0.q.c.h0.b.t.b(:25)
at b.f0.q.c.h0.b.t.a(:40)
at b.f0.q.c.g$a$i.d(:51)
at b.f0.q.c.g$a$i.a(:44)
at b.f0.q.c.y$a.c(:92)
at b.f0.q.c.y$c.b(:31)
at b.f0.q.c.g$a.m()
at b.f0.q.c.g.L(:179)
at b.f0.q.c.g.v(:196)
at b.f0.q.c.g$a$e.d(:91)
at b.f0.q.c.g$a$e.a(:44)
at b.f0.q.c.y$a.c(:92)
at b.f0.q.c.y$c.b(:31)
at b.f0.q.c.g$a.j()
at b.f0.q.c.g.k(:235)
at com.example.r8annotation.MainActivity.E(:19)
at com.example.r8annotation.MainActivity.onCreate(:11)
mk...@google.com <mk...@google.com>
[Deleted User] <[Deleted User]> #6
Just tested this again using the 4.0 gradlew stable release and it seems to still be broken, any news when this is expected to be fixed?
mk...@google.com <mk...@google.com> #7
Sorry, this accidentally dropped to the bottom of my inbox. Will take a look ASAP.
mk...@google.com <mk...@google.com> #8
The reproduction in b.j
class is:
kotlin.Metadata -> b.j:
And we cannot determine that the field bv is used reflective on that annotation. An easy fix here is basically to add
-keep class kotlin.Metadata { *; }
We should perhaps be able to remove the kotlin.Metadata.bv field in the annotation data as well, but as it is right now we will always generate the full kotlin.Metadata because we model it.
nfrederico@, is your problem resolved by adding the keep rule above?
[Deleted User] <[Deleted User]> #9
Is this a temporary fix? Using the -keep class kotlin.Metadata { *; }
on our proguard-rules.pro
file fixes the issue and our solution is now running on devices < api 24 compiled with gradlew 4.0.0!
Tyvm!
mk...@google.com <mk...@google.com> #10
Is this a temporary fix?
We are moving towards only keeping the kotlin.Metadata annotation for kept classes and if the annotation itself is kept instead of generating it for all classes in the output. This will solve this problem but, but if someone is doing a keep rule as so:
-keep class kotlin.Metadata { *** b1(); }
such that all members are not kept of the Metadata, reflectively instantiating the annotation will can still be a problem. There is not really a good solution since we are waiting until the very end to write out metadata, such that it is correct. I guess a solution would be to remove a field if it is not kept.
mk...@google.com <mk...@google.com> #11
Project: r8
Branch: master
commit 967475a14010e0a9d9bb3392c80745ad49843851
Author: Morten Krogh-Jespersen <mkroghj@google.com>
Date: Wed Aug 05 08:56:13 2020
Only emit kotlin metadata values for non-pruned annotation members
Bug: 161230424
Bug: 162900580
Change-Id: Ib74e75e89577626b0b1e511011f4e018bb9c9795
M src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
M src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
M src/test/java/com/android/tools/r8/kotlin/metadata/MetadataPrunedFieldsTest.java
M src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInRenamedTypeTest.java
M src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepTest.java
https://r8-review.googlesource.com/52667
ap...@google.com <ap...@google.com> #12
Branch: 2.1
commit 457065d1a288b3fedcc032104587cd280dae7915
Author: Morten Krogh-Jespersen <mkroghj@google.com>
Date: Wed Aug 05 11:36:06 2020
Version 2.1.57
Cherry-pick: Close stream of input source when dumping
CL:
Cherry-pick: Move synchronization of class initializer from DexClass to MethodColl
CL:
Cherry-pick: Add reproduction of removed fields in kotlin.Metadata
CL:
Cherry-pick: Only emit kotlin metadata values for non-pruned
annotation members
CL:
Bug: 160901582
Bug: 159194018
Bug: 161230424
Bug: 162900580
Bug: 152476580
Change-Id: I3e506acaba9333ed6bd31d7229f5982bab215696
M src/main/java/com/android/tools/r8/Version.java
M src/main/java/com/android/tools/r8/graph/DexClass.java
M src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
M src/main/java/com/android/tools/r8/graph/MethodCollection.java
M src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
M src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
M src/main/java/com/android/tools/r8/utils/AndroidApp.java
M src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
A src/test/java/com/android/tools/r8/kotlin/metadata/MetadataPrunedFieldsTest.java
M src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInRenamedTypeTest.java
M src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteKeepTest.java
A src/test/java/com/android/tools/r8/kotlin/metadata/metadata_pruned_fields/Main.java
A src/test/java/com/android/tools/r8/kotlin/metadata/metadata_pruned_fields/Methods.kt
Description
all required information.
Studio Build: 4.0.0 and above
Version of Gradle Plugin: 4.0.0 and above
Version of Gradle: 6.1.1 and above
Version of Java: Java8
OS: macOS
Steps to Reproduce:
1. Make a build using a gradle plugin version from 4.0.0 and above
2. Using reflection to access annotation information on devices with api < 24 causes an exception at libcore.reflect.AnnotationAccess.toAnnotationInstance
On versions of gradlew below 4.0.0 this is working fine, so I believe this is an issue with a newer version of R8
This is our code were we use reflection and is triggering this issue
```kotlin
value::class.constructors.first { it.parameters.isNotEmpty() }
.parameters.forEach { parameter ->
require(parameter.type.classifier == JsonPatchProperty::class) {
"Patch property ${
}
val jsonAnnotation = parameter.annotations.firstOrNull { it is Json }
if (jsonAnnotation != null) {
val jsonKey = (jsonAnnotation as Json).name
val request = jsonObj.optJSONObject(jsonKey)
if (request != null) {
patchRequestList += request.put("path", "/$jsonKey")
}
}
}
```
and this is the stacktrace of the issue
```
libcore.reflect.AnnotationAccess.toAnnotationInstance AnnotationAccess.java:659
libcore.reflect.AnnotationAccess.annotationSetToAnnotations AnnotationAccess.java:633
libcore.reflect.AnnotationAccess.getDeclaredAnnotations AnnotationAccess.java:161
java.lang.Class.getDeclaredAnnotations Class.java:743
kotlin.reflect.jvm.internal.impl.descriptors.runtime.components.ReflectClassStructure.b ReflectClassStructure.java:-1
kotlin.reflect.jvm.internal.impl.descriptors.runtime.components.ReflectKotlinClass$Factory.a ReflectKotlinClass.java:-1
kotlin.reflect.jvm.internal.impl.descriptors.runtime.components.ReflectKotlinClassFinder.d ReflectKotlinClassFinder.java:-1
kotlin.reflect.jvm.internal.impl.descriptors.runtime.components.ReflectKotlinClassFinder.c ReflectKotlinClassFinder.java:-1
kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaPackageScope$classes$1.a LazyJavaPackageScope.java:-1
kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaPackageScope$classes$1.invoke LazyJavaPackageScope.java:-1
kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke LockBasedStorageManager.java:-1
kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaPackageScope.H LazyJavaPackageScope.java:-1
kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaPackageScope.J LazyJavaPackageScope.java:-1
kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.JvmPackageScope.c JvmPackageScope.java:-1
kotlin.reflect.jvm.internal.impl.resolve.scopes.ChainedMemberScope.c ChainedMemberScope.java:-1
kotlin.reflect.jvm.internal.impl.resolve.scopes.AbstractScopeAdapter.c AbstractScopeAdapter.java:-1
kotlin.reflect.jvm.internal.impl.descriptors.FindClassInModuleKt.b FindClassInModuleKt.java:-1
kotlin.reflect.jvm.internal.impl.descriptors.FindClassInModuleKt.a FindClassInModuleKt.java:-1
kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.a KClassImpl.java:-1
kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke KClassImpl.java:-1
kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.c ReflectProperties.java:-1
kotlin.reflect.jvm.internal.ReflectProperties$Val.b ReflectProperties.java:-1
kotlin.reflect.jvm.internal.KClassImpl$Data.m KClassImpl.java:-1
kotlin.reflect.jvm.internal.KClassImpl.H KClassImpl.java:-1
kotlin.reflect.jvm.internal.KClassImpl.r KClassImpl.java:-1
kotlin.reflect.jvm.internal.KClassImpl$Data$constructors$2.a KClassImpl.java:-1
kotlin.reflect.jvm.internal.KClassImpl$Data$constructors$2.invoke KClassImpl.java:-1
kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.c ReflectProperties.java:-1
kotlin.reflect.jvm.internal.ReflectProperties$Val.b ReflectProperties.java:-1
kotlin.reflect.jvm.internal.KClassImpl$Data.j KClassImpl.java:-1
kotlin.reflect.jvm.internal.KClassImpl.h KClassImpl.java:-1
this.is.mypackage.data.api.utils.JsonPatchTransformer.a JsonPatchTransformer.java:-1
this.is.mypackage.data.api.services.base.BaseService$transformToPatch$1.a BaseService.java:-1
this.is.mypackage.data.api.services.base.BaseService$transformToPatch$1.call BaseService.java:-1
io.reactivex.internal.operators.single.SingleFromCallable.D SingleFromCallable.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleMap.D SingleMap.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleFlatMap.D SingleFlatMap.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleResumeNext.D SingleResumeNext.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleFlatMap.D SingleFlatMap.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleMap.D SingleMap.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleMap.D SingleMap.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleMap.D SingleMap.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleFlatMapCompletable.L SingleFlatMapCompletable.java:-1
io.reactivex.Completable.b Completable.java:-1
io.reactivex.internal.operators.completable.CompletableResumeNext.L CompletableResumeNext.java:-1
io.reactivex.Completable.b Completable.java:-1
io.reactivex.internal.operators.single.SingleFlatMapCompletable$FlatMapCompletableObserver.b SingleFlatMapCompletable.java:-1
io.reactivex.internal.operators.observable.ObservableElementAtSingle$ElementAtObserver.e ObservableElementAtSingle.java:-1
io.reactivex.internal.operators.observable.ObservableSwitchMap$SwitchMapObserver.f ObservableSwitchMap.java:-1
io.reactivex.internal.operators.observable.ObservableSwitchMap$SwitchMapInnerObserver.e ObservableSwitchMap.java:-1
io.reactivex.internal.operators.observable.ObservableMap$MapObserver.e ObservableMap.java:-1
io.reactivex.internal.operators.observable.ObservableMap$MapObserver.e ObservableMap.java:-1
io.reactivex.internal.operators.observable.ObservableFilter$FilterObserver.e ObservableFilter.java:-1
io.reactivex.internal.util.NotificationLite.a NotificationLite.java:-1
io.reactivex.internal.operators.observable.ObservableReplay$BoundedReplayBuffer.c ObservableReplay.java:-1
io.reactivex.internal.operators.observable.ObservableReplay$ReplaySource.c ObservableReplay.java:-1
io.reactivex.internal.operators.observable.ObservableReplay.s0 ObservableReplay.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableAutoConnect.s0 ObservableAutoConnect.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableFilter.s0 ObservableFilter.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableMap.s0 ObservableMap.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableMap.s0 ObservableMap.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableSwitchMap$SwitchMapObserver.e ObservableSwitchMap.java:-1
io.reactivex.internal.util.NotificationLite.a NotificationLite.java:-1
io.reactivex.internal.operators.observable.ObservableReplay$BoundedReplayBuffer.c ObservableReplay.java:-1
io.reactivex.internal.operators.observable.ObservableReplay$ReplaySource.c ObservableReplay.java:-1
io.reactivex.internal.operators.observable.ObservableReplay.s0 ObservableReplay.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableAutoConnect.s0 ObservableAutoConnect.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableSwitchMap.s0 ObservableSwitchMap.java:-1
io.reactivex.Observable.c Observable.java:-1
io.reactivex.internal.operators.observable.ObservableElementAtSingle.D ObservableElementAtSingle.java:-1
io.reactivex.Single.b Single.java:-1
io.reactivex.internal.operators.single.SingleFlatMapCompletable.L SingleFlatMapCompletable.java:-1
io.reactivex.Completable.b Completable.java:-1
io.reactivex.internal.operators.completable.CompletableSubscribeOn$SubscribeOnObserver.run CompletableSubscribeOn.java:-1
io.reactivex.Scheduler$DisposeTask.run Scheduler.java:-1
io.reactivex.internal.schedulers.ScheduledRunnable.run ScheduledRunnable.java:-1
io.reactivex.internal.schedulers.ScheduledRunnable.call ScheduledRunnable.java:-1
java.util.concurrent.FutureTask.run FutureTask.java:237
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run ScheduledThreadPoolExecutor.java:269
java.util.concurrent.ThreadPoolExecutor.runWorker ThreadPoolExecutor.java:1113
java.util.concurrent.ThreadPoolExecutor$Worker.run ThreadPoolExecutor.java:588
java.lang.Thread.run Thread.java:818
```