Kodein 7 Doesn't Protect Bound interface from R8 Dead Code Elimination
See original GitHub issueOur Android app is using R8 in full mode for release builds, and we’ve run into issues with Kodein 7, where it marks some of our interfaces as dead code, which causes a crash at runtime. There is no issue with Kodein 6.
Neither AgeValidator
nor AgeValidatorImpl
are referenced anywhere other than in the kodein binding.
interface AgeValidator {
fun validate(age: LocalDate): Boolean
}
internal class AgeValidatorImpl : AgeValidator {
override fun validate(age: LocalDate) = true // not the actual implementation; condensed for clarity
}
val validatorModule = DI.Module("Validators") {
bind<AgeValidator>() with provider {
AgeValidatorImpl()
}
}
class MyApp : Application(), DIAware {
override val di = DI.lazy {
import(validatorModule)
}
}
The crash at runtime is:
Binding bind<Any>() with ? { ? } must not override an existing binding.
Digging into the bytecode on Kodein 6 yields the following for AgeValidator
and AgeValidatorImpl
:
// AgeValidator
.class public interface abstract LiK0;
.super Ljava/lang/Object;
.source "AgeValidator.kt"
// AgeValidatorImpl; note that validate is not present because R8 eliminated it
.class public final LjK0;
.super Ljava/lang/Object;
.source "AgeValidator.kt"
# interfaces
.implements LiK0;
# direct methods
.method public constructor <init>()V
.registers 1
.line 18
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
For Kodein 7, AgeValidator has been completely eliminated and reduced into Any
, so that now AgeValidatorImpl simply extends Any
:
// AgeValidatorImpl
.class public final LDE1;
.super Ljava/lang/Object;
.source "AgeValidator.kt"
# direct methods
.method public constructor <init>()V
.registers 1
.line 18
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
The crash makes sense, because AgeValidator
gets replaced with Any
which transforms validatorModule
into:
val validatorModule = DI.Module("Validators") {
bind<Any>() with provider {
AgeValidatorImpl()
}
}
which crashes the second time this happens because we try binding Any
twice, and don’t allow overriding.
I’m not sure what changed in Kodein 7 that would cause R8 to not recognize usage of a class as a type parameter for bind
, but something did.
Issue Analytics
- State:
- Created 3 years ago
- Comments:20 (16 by maintainers)
Top GitHub Comments
FYI Kodein-DI 7.6 is out !
Looks like it’s working!
The following rules need to be added to proguard though:
It could be added on a project by project basis, but it would probably be easier if it was bundled with the library.