Fixed
Status Update
Comments
ze...@google.com <ze...@google.com>
js...@google.com <js...@google.com> #2
TL;DR: minifier should stick to abstract method's name in a super type.
public class Base implements Runnable {
public abstract a();
public void run() {
try { a(); } ...
}
}
public class Sub1 extends Base {
public final b() { ... } // should have been `a`
}
public class Sub2 ... // and more
------
All of affected classes came from "com.google.android.play:core", so I think it's fine to describe the whole details here.
First, here is the mapping of the problematic class:
com.google.android.play.core.internal.r -> b4.h.a.e.a.c.l:
com.google.android.play.core.tasks.i a -> d
1:1:boolean com.google.android.play.core.tasks.i.a(java.lang.Exception):0:0 -> run
1:1:void run():0 -> run
------
The disassembled code of class `b4.h.a.e.a.c.l` is:
.class public abstract Lb4/h/a/e/a/c/l;
.super Ljava/lang/Object;
# interfaces
.implements Ljava/lang/Runnable;
# instance fields
.field public final d:Lb4/h/a/e/a/d/i;
.annotation system Ldalvik/annotation/Signature;
value = {
"Lb4/h/a/e/a/d/i<",
"*>;"
}
.end annotation
.end field
# direct methods
.method public constructor <init>()V
.locals 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
const/4 v0, 0x0
iput-object v0, p0, Lb4/h/a/e/a/c/l;->d:Lb4/h/a/e/a/d/i;
return-void
.end method
.method public constructor <init>(Lb4/h/a/e/a/d/i;)V
.locals 0
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Lb4/h/a/e/a/d/i<",
"*>;)V"
}
.end annotation
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lb4/h/a/e/a/c/l;->d:Lb4/h/a/e/a/d/i;
return-void
.end method
# virtual methods
.method public abstract a()V
.end method
.method public final run()V
.locals 2
:try_start_0
invoke-virtual {p0}, Lb4/h/a/e/a/c/l;->a()V
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
return-void
:catch_0
move-exception v0
iget-object v1, p0, Lb4/h/a/e/a/c/l;->d:Lb4/h/a/e/a/d/i;
if-eqz v1, :cond_0
.line 1
iget-object v1, v1, Lb4/h/a/e/a/d/i;->a:Lb4/h/a/e/a/d/k;
invoke-virtual {v1, v0}, Lb4/h/a/e/a/d/k;->a(Ljava/lang/Exception;)Z
:cond_0
return-void
.end method
------
So, in the very first line of run(), it is calling its own abstract method `a`, which in turn raised AbstractMethodError at runtime. By adding:
invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/Class;->getName()Ljava/lang/String;
move-result-object v1
const-string v0, "[R8]"
invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
as a prologue of run(), I can confirm all sub-types of class `b4.h.a.e.a.c.l` missed to implement `a`. Actually, they implemented, but R8 renamed them to a different name. Here is one example subtype:
com.google.android.play.core.internal.s -> b4.h.a.e.a.c.m:
com.google.android.play.core.internal.r a -> e
com.google.android.play.core.internal.q b -> f
void a() -> b # <------------- :(
.class public final Lb4/h/a/e/a/c/m;
.super Lb4/h/a/e/a/c/l;
# instance fields
.field public final synthetic e:Lb4/h/a/e/a/c/l;
.field public final synthetic f:Lb4/h/a/e/a/c/k;
# direct methods
.method public constructor <init>(Lb4/h/a/e/a/c/k;Lb4/h/a/e/a/c/l;)V
.locals 0
iput-object p1, p0, Lb4/h/a/e/a/c/m;->f:Lb4/h/a/e/a/c/k;
iput-object p2, p0, Lb4/h/a/e/a/c/m;->e:Lb4/h/a/e/a/c/l;
invoke-direct {p0}, Lb4/h/a/e/a/c/l;-><init>()V
return-void
.end method
# virtual methods
.method public final b()V
.locals 2
iget-object v0, p0, Lb4/h/a/e/a/c/m;->f:Lb4/h/a/e/a/c/k;
iget-object v1, p0, Lb4/h/a/e/a/c/m;->e:Lb4/h/a/e/a/c/l;
invoke-static {v0, v1}, Lb4/h/a/e/a/c/k;->a(Lb4/h/a/e/a/c/k;Lb4/h/a/e/a/c/l;)V
return-void
.end method
------
After renaming all those `b` in subtypes, I saw the app is working. Just to confirm, will send a manually modified apk. Also, will prepare some logging to see why we chose a different name.
public class Base implements Runnable {
public abstract a();
public void run() {
try { a(); } ...
}
}
public class Sub1 extends Base {
public final b() { ... } // should have been `a`
}
public class Sub2 ... // and more
------
All of affected classes came from "com.google.android.play:core", so I think it's fine to describe the whole details here.
First, here is the mapping of the problematic class:
com.google.android.play.core.internal.r -> b4.h.a.e.a.c.l:
com.google.android.play.core.tasks.i a -> d
1:1:boolean com.google.android.play.core.tasks.i.a(java.lang.Exception):0:0 -> run
1:1:void run():0 -> run
------
The disassembled code of class `b4.h.a.e.a.c.l` is:
.class public abstract Lb4/h/a/e/a/c/l;
.super Ljava/lang/Object;
# interfaces
.implements Ljava/lang/Runnable;
# instance fields
.field public final d:Lb4/h/a/e/a/d/i;
.annotation system Ldalvik/annotation/Signature;
value = {
"Lb4/h/a/e/a/d/i<",
"*>;"
}
.end annotation
.end field
# direct methods
.method public constructor <init>()V
.locals 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
const/4 v0, 0x0
iput-object v0, p0, Lb4/h/a/e/a/c/l;->d:Lb4/h/a/e/a/d/i;
return-void
.end method
.method public constructor <init>(Lb4/h/a/e/a/d/i;)V
.locals 0
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Lb4/h/a/e/a/d/i<",
"*>;)V"
}
.end annotation
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lb4/h/a/e/a/c/l;->d:Lb4/h/a/e/a/d/i;
return-void
.end method
# virtual methods
.method public abstract a()V
.end method
.method public final run()V
.locals 2
:try_start_0
invoke-virtual {p0}, Lb4/h/a/e/a/c/l;->a()V
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
return-void
:catch_0
move-exception v0
iget-object v1, p0, Lb4/h/a/e/a/c/l;->d:Lb4/h/a/e/a/d/i;
if-eqz v1, :cond_0
.line 1
iget-object v1, v1, Lb4/h/a/e/a/d/i;->a:Lb4/h/a/e/a/d/k;
invoke-virtual {v1, v0}, Lb4/h/a/e/a/d/k;->a(Ljava/lang/Exception;)Z
:cond_0
return-void
.end method
------
So, in the very first line of run(), it is calling its own abstract method `a`, which in turn raised AbstractMethodError at runtime. By adding:
invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/Class;->getName()Ljava/lang/String;
move-result-object v1
const-string v0, "[R8]"
invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
as a prologue of run(), I can confirm all sub-types of class `b4.h.a.e.a.c.l` missed to implement `a`. Actually, they implemented, but R8 renamed them to a different name. Here is one example subtype:
com.google.android.play.core.internal.s -> b4.h.a.e.a.c.m:
com.google.android.play.core.internal.r a -> e
com.google.android.play.core.internal.q b -> f
void a() -> b # <------------- :(
.class public final Lb4/h/a/e/a/c/m;
.super Lb4/h/a/e/a/c/l;
# instance fields
.field public final synthetic e:Lb4/h/a/e/a/c/l;
.field public final synthetic f:Lb4/h/a/e/a/c/k;
# direct methods
.method public constructor <init>(Lb4/h/a/e/a/c/k;Lb4/h/a/e/a/c/l;)V
.locals 0
iput-object p1, p0, Lb4/h/a/e/a/c/m;->f:Lb4/h/a/e/a/c/k;
iput-object p2, p0, Lb4/h/a/e/a/c/m;->e:Lb4/h/a/e/a/c/l;
invoke-direct {p0}, Lb4/h/a/e/a/c/l;-><init>()V
return-void
.end method
# virtual methods
.method public final b()V
.locals 2
iget-object v0, p0, Lb4/h/a/e/a/c/m;->f:Lb4/h/a/e/a/c/k;
iget-object v1, p0, Lb4/h/a/e/a/c/m;->e:Lb4/h/a/e/a/c/l;
invoke-static {v0, v1}, Lb4/h/a/e/a/c/k;->a(Lb4/h/a/e/a/c/k;Lb4/h/a/e/a/c/l;)V
return-void
.end method
------
After renaming all those `b` in subtypes, I saw the app is working. Just to confirm, will send a manually modified apk. Also, will prepare some logging to see why we chose a different name.
js...@google.com <js...@google.com> #3
You don't need to wait for logging. I just reproduced the issue on master.
js...@google.com <js...@google.com> #4
The reproduction and fix is under review: https://r8-review.googlesource.com/c/r8/+/39060
Meanwhile, the attached is a patched R8 on 1.5.41
Meanwhile, the attached is a patched R8 on 1.5.41
to...@gmail.com <to...@gmail.com> #5
Thanks a lot I can confirm it works, full PlayCore update process tested (only immediate but I don't see a reason other mode don't work as the issue was at the start)
js...@google.com <js...@google.com> #6
Thank you for the confirmation! The fix (mentioned at comment #4 ) is landed on master and 1.5 branch (1.5.42)
wo...@gmail.com <wo...@gmail.com> #7
Any timeline when this will be released?
mk...@google.com <mk...@google.com> #8
It will be included in beta05 when that is released. You can use a version of R8 that includes the fix 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.42' // 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.42' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
to...@gmail.com <to...@gmail.com> #9
1.5.42 still have some potential major issue.
I'd not recommend using anything under 1.5.49. (Currently in prod with that one)
I'd not recommend using anything under 1.5.49. (Currently in prod with that one)
Description
This simple addition to my app:
implementation "com.google.android.play:core:1.6.0"
GlobalScope.launch(Dispatchers.IO) {
try {
val appUpdateManager = AppUpdateManagerFactory.create(ServiceLocator.applicationContext)
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
logError("AAA") {"Update: $appUpdateInfo ${appUpdateInfo.updateAvailability()}"}
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) {
// Request the update.
}
}
} catch (ignore: Exception) {
// Ignore
}
}
Crash with error
2019-05-28 10:40:15.308 10241-10272/? E/AndroidRuntime: FATAL EXCEPTION: AppUpdateService
Process: xxx, PID: 10241
java.lang.AbstractMethodError: abstract method "void b4.h.a.e.a.c.l.a()"
at b4.h.a.e.a.c.l.run(Unknown Source:0)
at android.os.Handler.handleCallback(Handler.java:874)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:198)
at android.os.HandlerThread.run(HandlerThread.java:65)
APK / Mapping sent by mail