gradle NotSerializableException:设置minifyEnabled为true后的Kotlin.UNINITIALIZED_VALUE

lvmkulzt  于 2023-04-30  发布在  Kotlin
关注(0)|答案(3)|浏览(213)

在应用程序build.gradle脚本中设置minifyEnabled true后,我开始收到这个异常:

Caused by: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = some.package.SomeClass)
    at android.os.Parcel.writeSerializable(Parcel.java:1767)
    …
Caused by: java.io.NotSerializableException: kotlin.UNINITIALIZED_VALUE

当我尝试将class SomeClass : Parcelable传递给另一个Activity时发生崩溃。
我试着用-keep class some.package.**.* { *; }把所有的app类加入白名单,但是没有成功。

u1ehiz5o

u1ehiz5o1#

我偶然发现了同样的问题,现在的答案是错误的:在lazy上添加@delegate:Transient将使反序列化时的backing字段无效。
由于该问题仅在minifyEnabled = true时发生,因此这是Proguard/R8问题。我通过在proguard-rules.pro中添加以下代码来解决这个问题:

-keep class * implements kotlin.Lazy {
    *;
}
whlutmcx

whlutmcx2#

懒惰代理在场景后面使用UNINITIALIZED_VALUE对象。它用来检查变量是否被声明。在某种程度上[需要更多信息]懒惰委托在代码缩减期间改变它们的行为。它会造成这样的情况,只要禁用minifyEnabled,那么传递带有惰性初始化字段的对象就可以正常工作,而不需要尝试序列化它。但是在启用minify之后,Java试图序列化UNINITIALIZED_VALUE,这在运行时抛出异常。
不幸的是,stacktrace并没有告诉你必须更新哪个类中的哪个字段。至少它会告诉你哪个主类包含你的坏了的Serializable类。
让我们假设在这种情况下some.package.SomeClass包含AnotherClass字段。要解决这个问题,你需要找到所有实现Serializable的lazy class字段。然后将@delegate:Transient添加到它们,例如。

class AnotherClass: Serializable {

    …

    @delegate:Transient // <- add this
    val myLazyField by lazy { "Kotlin, why?!" }
}
b4qexyjb

b4qexyjb3#

我也遇到了同样的问题。出现以下pro-guard设置以解决问题:

-keepclassmembers class * implements java.io.Serializable {
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

相关问题