Fixed
Status Update
Comments
uc...@google.com <uc...@google.com>
mk...@google.com <mk...@google.com> #2
Thank you for the report. Could I ask you to try a later version where a few reported bugs have been fixed by adding the following to your build.gradle:
buildscript {
repositories {
maven {
url 'http://storage.googleapis.com/r8-releases/raw '
}
}
dependencies {
classpath 'com.android.tools:r8:1.4.96' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
If it still fails, would it be possible to share your APK? You can send it privately to mkroghj@google.com
buildscript {
repositories {
maven {
url '
}
}
dependencies {
classpath 'com.android.tools:r8:1.4.96' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
If it still fails, would it be possible to share your APK? You can send it privately to mkroghj@google.com
as...@gmail.com <as...@gmail.com> #3
I tried the later version of R8, but unfortunately the issue is still occurring. I'll share the APK via email.
mk...@google.com <mk...@google.com> #4
I have received it at will take a look.
mk...@google.com <mk...@google.com> #5
For some reason still unknown we remove the implementation of onTaskFinished. As a result, the VM cannot find an implementation and will report an abstract method error. It looks like the setup is a bit more complicated than initially described because there exists some interface:
public interface SubOnTaskFinishedListener extends OnTaskFinishedListener { ... }
And also:
public abstract class SubTask extends Task<...> {
public SubTask(SubOnTaskFinishedListener impl) { ... }
}
I have tried to reproduce it locally by adding a structure similar to yours but with no success. Is it possible for you to:
1) Share your code privately - we will easier be able to find the bug and solve it.
2) If not, could you say what the original names of these are such that I can put some logging information into R8:
com.<your_company>.android.<your_project>.ui.za
c.p.a.c.d.E$a
c.p.a.c.d.a.e$a
You can send either privately to mkroghj@google.com.
Right now we suspect that the enqueuer may not realize that the implementations of SubOnTaskFinishedListener can be called and removes them, leaving OnTaskFinishedListener without a correct implementation.
public interface SubOnTaskFinishedListener extends OnTaskFinishedListener { ... }
And also:
public abstract class SubTask extends Task<...> {
public SubTask(SubOnTaskFinishedListener impl) { ... }
}
I have tried to reproduce it locally by adding a structure similar to yours but with no success. Is it possible for you to:
1) Share your code privately - we will easier be able to find the bug and solve it.
2) If not, could you say what the original names of these are such that I can put some logging information into R8:
com.<your_company>.android.<your_project>.
c.p.a.c.d.E$a
c.p.a.c.d.a.e$a
You can send either privately to mkroghj@google.com.
Right now we suspect that the enqueuer may not realize that the implementations of SubOnTaskFinishedListener can be called and removes them, leaving OnTaskFinishedListener without a correct implementation.
as...@gmail.com <as...@gmail.com> #6
Sorry I failed to mention the sub-interface and sub-class. I was able to reproduce the issue using this minimal code which parallels our current implementation:
// Task.java:
public abstract class Task<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
protected OnTaskFinishedListener<Result> mListener;
public interface OnTaskFinishedListener<Result> {
void onTaskFinished(Result result);
}
public Task(OnTaskFinishedListener<Result> listener) {
mListener = listener;
}
@Override
protected void onPostExecute(Result result) {
if (mListener != null) {
mListener.onTaskFinished(result);
}
}
}
// OuterClass.java:
public class OuterClass {
public static class Result {
private Result() {
}
}
public interface Callback extends Task.OnTaskFinishedListener<Result> {
@Override
void onTaskFinished(Result result);
}
private static class ConcreteTask extends Task<Void, Void, Result> {
public ConcreteTask(Callback listener) {
super(listener);
}
@Override
protected Result doInBackground(Void... params) {
return new Result();
}
}
public static void startTask(Callback callback) {
new ConcreteTask(callback).execute();
}
}
// AnActivity.java:
public class AnActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OuterClass.startTask(result -> Toast.makeText(this, "Test", Toast.LENGTH_SHORT).show());
}
}
// Task.java:
public abstract class Task<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
protected OnTaskFinishedListener<Result> mListener;
public interface OnTaskFinishedListener<Result> {
void onTaskFinished(Result result);
}
public Task(OnTaskFinishedListener<Result> listener) {
mListener = listener;
}
@Override
protected void onPostExecute(Result result) {
if (mListener != null) {
mListener.onTaskFinished(result);
}
}
}
// OuterClass.java:
public class OuterClass {
public static class Result {
private Result() {
}
}
public interface Callback extends Task.OnTaskFinishedListener<Result> {
@Override
void onTaskFinished(Result result);
}
private static class ConcreteTask extends Task<Void, Void, Result> {
public ConcreteTask(Callback listener) {
super(listener);
}
@Override
protected Result doInBackground(Void... params) {
return new Result();
}
}
public static void startTask(Callback callback) {
new ConcreteTask(callback).execute();
}
}
// AnActivity.java:
public class AnActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OuterClass.startTask(result -> Toast.makeText(this, "Test", Toast.LENGTH_SHORT).show());
}
}
mk...@google.com <mk...@google.com> #7
The small reproduction was perfect and the error has been located and fixed. Could I ask you to try out the new version by adding the following to your build.gradle:
buildscript {
repositories {
maven {
url 'http://storage.googleapis.com/r8-releases/raw '
}
}
dependencies {
classpath 'com.android.tools:r8:1.5.45' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
buildscript {
repositories {
maven {
url '
}
}
dependencies {
classpath 'com.android.tools:r8:1.5.45' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
js...@google.com <js...@google.com> #8
mk...@google.com <mk...@google.com> #9
Yes :) thx Jinseong! I have edited the comment.
as...@gmail.com <as...@gmail.com> #10
Yes, this appears to be fixed with 1.5.45. Thanks! Will this fix be in the next release of the Android Gradle Plugin?
mk...@google.com <mk...@google.com> #11
Thank you for trying out the fix and reporting the error. I believe it will be in the next release of AGP which I think will ship with the next beta of studio.
am...@gmail.com <am...@gmail.com> #12
Android gradle Plug-in version: 3.4.1
Gradle version: 5.1.1
compile sdk ver: 28
target sdk: 28
source/target compatibility Java 1.8
R8 version: 1.5.45 (build c1a35fd9ea047a0f504c765a739c4a1cc1dcc8bd from go/r8bot (luci-r8-ci-jctf-1-i2qt))
Hi everyone, got slightly different variation of the same issue on latest version of R8.
I have attached a sample gradle project to demonstrate it.
Use case:
1. We have some classes available on android device that are not in compile classpath.
2. We have created a client api jar/aar, compiled against these classes. For some reason it uses a lambda callback.
3. Client adds our client api jar/aar as a dependency
4. Client adds a rule to keep all classes in client jar package with all their members (e.g. -keep class com.example.clientlib.** { *; })
5. Client compiles the application and runs it.
What happens:
The interface implemented by lambda is not in compile classpath. R8 couldn't access it, so it renamed the method.
When receiving callback, the application crashes with AbstractMethodError because the actual callback method is not implemented anymore.
The line I see in mapping file:
com.example.clientlib.-$$Lambda$ClientApiClass$_cx-zzRinEQOn8-MweraX5tLObQ -> a.a.a.a:
com.example.clientlib.-$$Lambda$ClientApiClass$_cx-zzRinEQOn8-MweraX5tLObQ INSTANCE -> a
The lambda got obfuscated even though there is a rule to keep EVERYTHING in this package.
Adding the rule -keep class * implements com.example.bootclasspathlib.SystemClass$Listener { *; } also has no effect, lambda gets obfuscated.
Verified with dexdump.
After disabling R8:
proguard notifies me that there are missing classes that are referenced
Warning: com.example.clientlib.ClientApiClass: can't find referenced class com.example.bootclasspathlib.SystemClass
Warning: com.example.clientlib.ClientApiClass: can't find referenced class com.example.bootclasspathlib.SystemClass$Listener
I am forced to add -dontwarn com.example.bootclasspathlib.** to my config file
After compiling I see that lambda is left intact and everything works fine. Verified with dexdump.
Afterword:
Unfortunately I have found no workaround except recompiling the library with no lambda expressions.
Could you please make R8 either keep the method names if the interface wasn't found in classpath or at least give some workaround for cases like this?
Would be very helpfui if specified -keep rules also applied to lambdas, which is not the case for now.
Because it is not always a jar/aar you can easily modify.
If example above seems too artificial, I can give you a more realistic one:
Launcher3Quickstep uses a sysui_shared.jar as a user interface to access SystemUI.
https://android.googlesource.com/platform/packages/apps/Launcher3/+/refs/heads/master/quickstep/libs/sysui_shared.jar
There is a lambda in class com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier used for callback
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java#54
Launcher3Quickstep built outside AOSP tree with gradle+R8+D8 crashes the same way.
The same thing happens to the launcher developed by our team when we've implemented the same feature.
The only workaround was to recompile the SystemUISharedLib with anonymous class instead of lambda.
Gradle version: 5.1.1
compile sdk ver: 28
target sdk: 28
source/target compatibility Java 1.8
R8 version: 1.5.45 (build c1a35fd9ea047a0f504c765a739c4a1cc1dcc8bd from go/r8bot (luci-r8-ci-jctf-1-i2qt))
Hi everyone, got slightly different variation of the same issue on latest version of R8.
I have attached a sample gradle project to demonstrate it.
Use case:
1. We have some classes available on android device that are not in compile classpath.
2. We have created a client api jar/aar, compiled against these classes. For some reason it uses a lambda callback.
3. Client adds our client api jar/aar as a dependency
4. Client adds a rule to keep all classes in client jar package with all their members (e.g. -keep class com.example.clientlib.** { *; })
5. Client compiles the application and runs it.
What happens:
The interface implemented by lambda is not in compile classpath. R8 couldn't access it, so it renamed the method.
When receiving callback, the application crashes with AbstractMethodError because the actual callback method is not implemented anymore.
The line I see in mapping file:
com.example.clientlib.-$$Lambda$ClientApiClass$_cx-zzRinEQOn8-MweraX5tLObQ -> a.a.a.a:
com.example.clientlib.-$$Lambda$ClientApiClass$_cx-zzRinEQOn8-MweraX5tLObQ INSTANCE -> a
The lambda got obfuscated even though there is a rule to keep EVERYTHING in this package.
Adding the rule -keep class * implements com.example.bootclasspathlib.SystemClass$Listener { *; } also has no effect, lambda gets obfuscated.
Verified with dexdump.
After disabling R8:
proguard notifies me that there are missing classes that are referenced
Warning: com.example.clientlib.ClientApiClass: can't find referenced class com.example.bootclasspathlib.SystemClass
Warning: com.example.clientlib.ClientApiClass: can't find referenced class com.example.bootclasspathlib.SystemClass$Listener
I am forced to add -dontwarn com.example.bootclasspathlib.** to my config file
After compiling I see that lambda is left intact and everything works fine. Verified with dexdump.
Afterword:
Unfortunately I have found no workaround except recompiling the library with no lambda expressions.
Could you please make R8 either keep the method names if the interface wasn't found in classpath or at least give some workaround for cases like this?
Would be very helpfui if specified -keep rules also applied to lambdas, which is not the case for now.
Because it is not always a jar/aar you can easily modify.
If example above seems too artificial, I can give you a more realistic one:
Launcher3Quickstep uses a sysui_shared.jar as a user interface to access SystemUI.
There is a lambda in class com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier used for callback
Launcher3Quickstep built outside AOSP tree with gradle+R8+D8 crashes the same way.
The same thing happens to the launcher developed by our team when we've implemented the same feature.
The only workaround was to recompile the SystemUISharedLib with anonymous class instead of lambda.
su...@gmail.com <su...@gmail.com> #13
Is there an update to this question.
mk...@google.com <mk...@google.com> #14
The entire desugaring pipeline has been changed. One can still not put any keep rules on generated lambda classes, however, the lambda class should implement the interface without minification so the app should work. If you still see issues with newer versions of R8 please let me know.
Description
java.lang.AbstractMethodError: abstract method "void com.example.database.tasks.Task$OnTaskFinishedListener.onTaskFinished(java.lang.Object)"
at com.example.database.tasks.Task.onPostExecute(SourceFile:39)
at android.os.AsyncTask.finish(AsyncTask.java:667)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:684)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Here are the relevant parts of how the above classes are defined:
public abstract class Task<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
public interface OnTaskFinishedListener<Result> {
void onTaskFinished(Result result);
}
protected OnTaskFinishedListener<Result> mListener;
public Task(OnTaskFinishedListener<Result> listener) {
mListener = listener;
}
@Override
protected void onPostExecute(Result result) {
if (mListener != null) {
mListener.onTaskFinished(result);
}
}
}
When a Task is created, the OnTaskFinishedListener is provided to the constructor as a Java 8 lambda.
Please let me know if there are any other details you need.